利用Ionic2 + angular4实现一个地区选择组件


Posted in Javascript onJuly 27, 2017

前言

本文主要给大家介绍的是关于利用Ionic2 + angular4实现一个地区选择组件的相关内容,为什么会有这篇文章?主要是因为最近在项目重构的过程中,发现之前用mobiscroll写的地区选择指令在angular2中很难重用(毕竟是用typeScript)。于是就萌生了自己写一个组件的想法。

想和之前一样基于mobiscroll去写,但是发现非常耗费精力,于是某日万般无奈这下搜了一下相关的组件,不出所料已经有人写了。https://www.npmjs.com/package...但是此组件并不符合我的要求。我不是单纯的选择省市区,还可能是选择省市或者省。于是参照此项目基于ionic2的picker写了一个公用组件。下面话不多说了,感兴趣的朋友们下面来一起看看详细的介绍:

具体代码如下:

AreasSelect.ts

import {PickerController} from "ionic-angular";
import {Component, EventEmitter, Output, Input} from "@angular/core";
import {areasList} from "../../datasource/areas";

@Component({
 selector: 'areas-select',
 templateUrl: 'areasSelect.com.html',
})
export class AreasSelect {
 constructor(protected Picker: PickerController) {
 }
 private picker;
 private provinceCol = 0; // 省列
 private cityCol = 0; // 市列
 private regionCol = 0; // 区列
 private pickerColumnCmps; // picker纵列数据实例
 private isOpen = false; // 是否被创建
 private pickerCmp; // picker 实例
 private value = ''; // 选中后的数据
 @Input() citiesData = areasList; // 地区数据(默认为areas.ts的数据)
 @Input() cancelText = '关闭'; // 关闭按钮文本
 @Input() doneText = '完成'; // 完成按钮文本
 @Input() separator = ''; // 数据衔接模式
 @Input() level = 3; // 等级设置 最高为三级
 /**
 * 关闭时触发的事件
 * 没有值返回
 * @type {EventEmitter}
 */
 @Output() cancel: EventEmitter<any> = new EventEmitter(); // 关闭事件
 /**
 * 完成时触发的事件
 * 返回值为obj
 * obj = {data: object,value: string} data为对应的省市区和编码
 * @type {EventEmitter}
 */
 @Output() done: EventEmitter<any> = new EventEmitter(); // 完成事件
 /**
 * 打开地区选择器
 * 基本思路
 * 1.创建picker
 * 2. 先把数据处理成省市区分开的数组
 * 3. 将数据以列的形式给到picker
 * 4. 设置数据显示样式(picker)
 * 5. 生成picker
 */
 private open() {
 let pickerOptions = {
 buttons: [
 {
 text: this.cancelText,
 role: 'cancel',
 handler:() => {
 this.cancel.emit(null);
 }
 },
 {
 text: this.doneText,
 handler: (data) =>{
 this.onChange(data);
 this.done.emit({
 data: data,
 value: this.value
 });
 }
 }
 ]
 };
 this.picker = this.Picker.create(pickerOptions);
 this.generate();// 加载
 this.validate(this.picker); // 渲染
 this.picker.ionChange.subscribe(() => {
 this.validate(this.picker);
 });
 // 生成
 this.picker.present(pickerOptions).then(() => {
 this.pickerCmp = this.picker.instance;
 this.pickerColumnCmps = this.pickerCmp._cols.toArray();
 this.pickerColumnCmps.forEach(function (col) {
 return col.lastIndex = -1;
 });
 });
 this.isOpen = true;
 this.picker.onDidDismiss(function () {
 this.isOpen = false;
 });
 }

 /** 对数据进行处理,并移交给picker
 *
 */
 private generate() {
 let values = this.value.toString().split(this.separator);
 // Add province data to picker
 let provinceCol = {
 name: 'province',
 options: this.citiesData.map(function (province) {
 return {text: province.name, value: province.code, disabled: false};
 }),
 selectedIndex: 0
 };
 let provinceIndex = this.citiesData.findIndex(function (option) {
 return option.name == values[0];
 });
 provinceIndex = provinceIndex === -1 ? 0 : provinceIndex;
 provinceCol.selectedIndex = provinceIndex;
 this.picker.addColumn(provinceCol);
 // Add city data to picker
 let cityColData = this.citiesData[provinceCol.selectedIndex].children;
 let cityCol;

 if (this.level >= 2) {
 cityCol = {
 name: 'city',
 options: cityColData.map(function (city) {
 return {text: city.name, value: city.code, disabled: false};
 }),
 selectedIndex: 0
 };
 let cityIndex = cityColData.findIndex(function (option) {
 return option.name == values[1];
 });
 cityIndex = cityIndex === -1 ? 0 : cityIndex;
 cityCol.selectedIndex = cityIndex;
 this.picker.addColumn(cityCol);
 }
 // Add region data to picker
 let regionData, regionCol;

 if (this.level === 3) {
 regionData = this.citiesData[provinceCol.selectedIndex].children[cityCol.selectedIndex].children;
 regionCol = {
 name: 'region',
 options: regionData.map(function (city) {
 return {text: city.name, value: city.code, disabled: false};
 }),
 selectedIndex: 0
 };
 let regionIndex = regionData.findIndex(function (option) {
 return option.name == values[2];
 });
 regionIndex = regionIndex === -1 ? 0 : regionIndex;
 regionCol.selectedIndex = regionIndex;
 this.picker.addColumn(regionCol);
 }
 this.divyColumns(this.picker);
 }

 /**设置数据显示样式
 * @param picker
 */
 private divyColumns(picker) {
 let pickerColumns = this.picker.getColumns(); // 获取列数据
 let columns = [];
 pickerColumns.forEach(function (col, i) {
 columns.push(0);
 col.options.forEach(function (opt) {
 if (opt && opt.text && opt.text.length > columns[i]) {
 columns[i] = opt.text.length;
 }
 });
 });
 if (columns.length === 2) {
 let width = Math.max(columns[0], columns[1]);
 pickerColumns[0].align = 'right';
 pickerColumns[1].align = 'left';
 pickerColumns[0].optionsWidth = pickerColumns[1].optionsWidth = width * 17 + "px";
 }
 else if (columns.length === 3) {
 let width = Math.max(columns[0], columns[2]);
 pickerColumns[0].align = 'right';
 pickerColumns[1].columnWidth = columns[1] * 33 + "px";
 pickerColumns[0].optionsWidth = pickerColumns[2].optionsWidth = width * 17 + "px";
 pickerColumns[2].align = 'left';
 }
 }

 /**
 * 验证数据
 * @param picker
 */
 private validate(picker) {
 let _this = this;
 let columns = picker.getColumns();
 let provinceCol = columns[0];
 let cityCol = columns[1];
 let regionCol = columns[2];
 if (cityCol && this.provinceCol != provinceCol.selectedIndex) {
 cityCol.selectedIndex = 0;
 let cityColData = this.citiesData[provinceCol.selectedIndex].children;
 cityCol.options = cityColData.map(function (city) {
 return {text: city.name, value: city.code, disabled: false};
 });
 if (this.pickerColumnCmps && cityCol.options.length > 0) {
 setTimeout(function () {
 return _this.pickerColumnCmps[1].setSelected(0, 100);
 }, 0);
 }
 }
 if (regionCol && (this.cityCol != cityCol.selectedIndex || this.provinceCol != provinceCol.selectedIndex)) {
 let regionData = this.citiesData[provinceCol.selectedIndex].children[cityCol.selectedIndex].children;
 regionCol.selectedIndex = 0;
 regionCol.options = regionData.map(function (city) {
 return {text: city.name, value: city.code, disabled: false};
 });
 if (this.pickerColumnCmps && regionCol.options.length > 0) {
 setTimeout(function () {
 return _this.pickerColumnCmps[2].setSelected(0, 100);
 }, 0);
 }
 }
 this.provinceCol = provinceCol.selectedIndex;
 this.cityCol = cityCol ? cityCol.selectedIndex : 0;
 this.regionCol = regionCol ? regionCol.selectedIndex : 0;
 }

 /**
 * 设置value
 * @param newData
 */
 private setValue(newData) {
 if (newData === null || newData === undefined) {
 this.value = '';
 }
 else {
 this.value = newData;
 }
 }

 /**
 * 获取value值
 * @returns {string}
 */
 private getValue() {
 return this.value;
 }

 /**
 * 改变value值的显示
 * @param val
 */
 private onChange(val) {
 this.setValue(this.getString(val));
 }

 /**
 * 获取当前选择的地区数据
 * @param newData
 * @returns {string}
 */
 private getString(newData) {
 if (newData['city']) {
 if (newData['region']) {
 return "" + newData['province'].text + this.separator + (newData['city'].text || '') + this.separator + (newData['region'].text || '');
 }
 return "" + newData['province'].text + this.separator + (newData['city'].text || '');
 }
 return "" + newData['province'].text;
 }
}

areasSelect.com.html

其实是不需要对应的template的,但是为了能和父级传参,这里创建了一个空的template

<div></div>

具体用法:

在需要用到的页面调用

test.page.html

<ion-content>
 <button ion-button block icon-left color="light" (tap)="showAreasSelect()">地区选择</button>
</ion-content>
<areas-select #areasSelect [level]="3" (cancel)="closeSelect()" (done)="done($event)"></areas-select>

test.page.ts

import {Component, ElementRef, Injector, ViewChild} from "@angular/core";
import {BasePage} from "../base.page";

@Component({
 templateUrl: 'test.page.html',
 styles: []
})
export class TestPage extends BasePage {
 constructor(protected rt: ElementRef, protected ij: Injector) {
 super(rt, ij);
 }
 @ViewChild('areasSelect') areasSelect;
 showAreasSelect() {
 this.areasSelect.open();
 }
 done(data) {
 this.showAlert(JSON.stringify(data));
 }
 closeSelect() {
 this.showAlert('you click close');
 } 
}

没有地区数据json或ts的文件可以去这里获取:http://xiazai.3water.com/201707/yuanma/regional_data(3water.com).rar

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
YUI模块开发原理详解
Nov 18 Javascript
让checkbox不选中即将选中的checkbox不选中
Jul 11 Javascript
使用jquery动态加载js文件的方法
Dec 24 Javascript
jQuery购物车插件jsorder用法(支持后台处理程序直接转换成DataTable处理)
Jun 08 Javascript
全面解析Bootstrap中tooltip、popover的使用方法
Jun 13 Javascript
AngularJS入门教程之更多模板详解
Aug 19 Javascript
JavaScript制作颜色反转小游戏
Sep 25 Javascript
js实现密码强度检验
Jan 15 Javascript
JS开发中百度地图+城市联动实现实时触发查询地址功能
Apr 13 Javascript
用WebStorm进行Angularjs 2开发(环境篇:Windows 10,Angular-cli方式)
Dec 05 Javascript
浏览器事件循环与vue nextTicket的实现
Apr 16 Javascript
Vue3.0中Ref与Reactive的区别示例详析
Jul 07 Vue.js
vue单页应用中如何使用jquery的方法示例
Jul 27 #jQuery
详解win7 cmd执行vue不是内部命令的解决方法
Jul 27 #Javascript
Vue2.0如何发布项目实战
Jul 27 #Javascript
在Vue中如何使用Cookie操作实例
Jul 27 #Javascript
vue 怎么创建组件及组件使用方法
Jul 27 #Javascript
详解Angular-cli生成组件修改css成less或sass的实例
Jul 27 #Javascript
Vue中如何实现轮播图的示例代码
Jul 27 #Javascript
You might like
《魔兽争霸3:重制版》更新 多项视觉效果调整
2020/05/04 魔兽争霸
Zend Guard一些常见问题解答
2008/09/11 PHP
详解PHP中的 input属性(隐藏 只读 限制)
2017/08/14 PHP
php文件后缀不强制为.php的实操方法
2019/09/18 PHP
用jscript实现新建和保存一个word文档
2007/06/15 Javascript
JavaScript中Cookie操作实例
2015/01/09 Javascript
jQuery实现表格行上移下移和置顶的方法
2015/05/22 Javascript
jQuery中队列queue()函数的实例教程
2016/05/03 Javascript
JavaScript数据操作_浅谈原始值和引用值的操作本质
2016/08/23 Javascript
浅析Javascript的自动分号插入(ASI)机制
2016/09/29 Javascript
Bootstrap3 Grid system原理及应用详解
2016/09/30 Javascript
Angular2 Service实现简单音乐播放器服务
2017/02/24 Javascript
nodejs构建本地web测试服务器 如何解决访问静态资源问题
2017/07/14 NodeJs
JavaScript屏蔽Backspace键的实现代码
2017/11/02 Javascript
vue + webpack如何绕过QQ音乐接口对host的验证详解
2018/07/01 Javascript
Vue路由钩子之afterEach beforeEach的区别详解
2018/07/15 Javascript
简单说说angular.json文件的使用
2018/10/29 Javascript
Vue press 支持图片放大功能的实例代码
2018/11/09 Javascript
vue实现搜索功能
2019/05/28 Javascript
jQuery操作cookie的示例代码
2019/06/05 jQuery
Angular8路由守卫原理和使用方法
2019/08/29 Javascript
jQuery AJAX应用实例总结
2020/05/19 jQuery
微信小程序实现canvas分享朋友圈海报
2020/06/21 Javascript
[03:00]2018完美盛典_最佳英雄奖
2018/12/17 DOTA
python使用wxpython开发简单记事本的方法
2015/05/20 Python
Python中的sort()方法使用基础教程
2017/01/08 Python
python使用super()出现错误解决办法
2017/08/14 Python
Python实现提取XML内容并保存到Excel中的方法
2018/09/01 Python
Python实现RabbitMQ6种消息模型的示例代码
2020/03/30 Python
详解python安装matplotlib库三种失败情况
2020/07/28 Python
汽车技术服务与营销专业在籍生自荐信
2013/09/28 职场文书
大学毕业生自荐书怎么写?
2014/01/06 职场文书
新闻编辑专业毕业自荐书范文
2014/02/05 职场文书
党风廉政建设个人总结
2015/03/06 职场文书
2015年手术室工作总结
2015/05/11 职场文书
为Java项目添加Redis缓存的方法
2021/05/18 Redis