Angular4自制一个市县二级联动组件示例


Posted in Javascript onNovember 21, 2017

最近遇到了不少问题,真的是命运多舛。Angular真是让人又爱又恨的框架,恨的是资料太少,遇到问题无从下手。爱的是许多其他框架难以做到的功能,angular却可以轻松做到。

话不多说,最近遇到了一个旧项目改造的问题。拿到前同事做的页面效果:

Angular4自制一个市县二级联动组件示例

第一眼就看到了这三个下拉框,按捺不住好奇心的我点了点。原来,第一个下拉框可以选择市属和省属,如果选择市属,那么后面就会出现市、县级两个下拉框,如果是省属,那就隐藏了,这个挺容易的。然后就是要选择市之后,区下拉框要有对应区县选项。emmmm,很典型的二级联动,不过既然分析完了思路,那就开始做吧!首先呢,数据肯定要从后端同事那里拿,调用他的接口把数据填充进去。看看数据是什么样子的:

Angular4自制一个市县二级联动组件示例

数据略多,就不全部贴出来了。把实体bean创建一下,

// 市级实体类
export class City {

  // 市级id
  cityId: string;

  // 所属类型(0.市属 1.省属)
  cityType: number;

  // 市级名称(可选属性,若cityType为1时,可不填)
  cityName: string;

  // 所属区县
  counties?: Array<Country>;

}

// 区县级实体类
export class Country {

  // 区县id
  countryId: string;

  // 区县名称
  countryName: string;

}

// 填写市县类
export class CityAndCountry {

  // 市级id
  cityId: string;

  // 县级id
  countryId: string;

  // 市级类型
  cityType: number;

  // 市县级实体构造器 
  constructor() {
    // 给市级id赋予一个真实城市的id初始值
    this.cityId = '***';
    // 同上
    this.countryId = '***';
    // 同上
    this.cityType = 0;
  }
}

实体完成了,开始准备获取数据并填充至实体:

// 二级联动组件
export class CityAreaComponent implements OnInit, OnDestroy {

  // 结果码 (用于页面处理显示标识)
  result_code: number;

  // 市级实体声明
  city: City[];

  // 县区级实体声明
  country: Country[];

  // 市县、区级填写实体声明
  cac: CityAndCountry;

  // 声明订阅对象
  subscript: Subscription;

  /**
  * 构造器
  * @param {CityService} service 注入服务
  */
  constructor (private service: CityService) {
    // 结果码 (-1.网络或其他异常 0.无内容 1.请求成功 2.请等待)
    this.result_code = 2;
    // 初始化填写市区、县级填写实体
    cac = new CityAndCountry();
    // 初始化数组(这步很重要,有很多人说使用数组相关函数会报未定义异常,是因为没有初始化的原因)
    this.city = [];
    this.country = [];
    // 初始化订阅对象
    this.subscript = new Subscription();
  }

  /**
  * 生命周期初始化钩子(生命周期尽量按执行顺序来写,养成好习惯)
  */
  ngOnInit(): void {
    this.getCityArea();
  }

  /** 获取市县数据 */
  getCityArea() {
    /** 将请求交付服务处理(service代码比较简单,就不贴了) */
    this.subscript = this.service.getCityArea().subscribe(res => {
      /** 获取json请求结果 */
      const result = res.json();
      /** 判断结果返回码 */
      switch (result['code']) {
        /** 请求成功,并且有值 */
        case 200:
        /** 改变初始返回码 */
        this.result_code = 1;
        /** 获取并填充数据 */
        this.city = json['city'];
        break;
        /** 其他情况不重复赘述 */
      }
    }, err => {
      /** 显示预设异常信息提示给用户 */
      this.result_code = -1;
      /** 打印log,尽量使用日志产出 */
      console.error(err);
    });
  }

  /** 生命周期销毁钩子 */
  ngOnDestroy(): void {
    /** 取消订阅 */
    this.subscript.unsubscribe();
  }
}

由于此处是单服务请求,为了让代码比较清晰直观,这里我就不做封装处理了。数据获取了之后就该填充到展示界面了:

<!-- 所属类型(此处固定,一般为获取后端数据字典数据) -->
<select class="city_type" [value]="cac.cityType" [(ngModel)]="cac.cityType">
  <!-- 所传内容为整数型 -->
  <option value=0>市属</option>
  <option value=1>省属</option>
</select>

<!-- 市级选择(类型为省属时隐藏) -->
<select class="city" [value]="cac.cityId" [(ngModel)]="cac.cityId" *ngIf="city.cityType==0">
  <!-- 遍历城市数组 -->
  <option *ngFor="let opt of option" [value]="opt.cityId">{{opt.cityName}}</option>
</select>

这时候,我们发现县级获取起来好像并不能直接获取,怎么办呢?我突然想到,我在ts里面声明一个变量获取市级选择的id号,然后再拿id去找下属县区,这样就可以轻松拿到了。既然要实时获取变化,那我们就实现检测变化钩子:

// 二级联动组件
export class CityAreaComponent implements OnInit, OnDestroy, DoCheck{
  // 声明县区级数组
  country: Array<Country>;

  constructor() {
    /** 重复代码不赘述 */
    /** 初始化数组 */
    country = [];
  }  

  /** 生命周期检测变化钩子 */
  ngDoCheck(): void {
    /** 遍历市级数组 */
    for (let i = 0; i < this.city.length; i++) {
      /** 若选择的市级id和市级数组中的id相吻合 */
      if (this.city[i].id == this.cac.countryId) {
        /** 将该索引下的counties数组赋予给区县级数组 */
        this.country = this.city[i].counties;
      }
      /** 我们无法避免直辖市的情况,所以多一重判断 */
      if (this.country.length > 0) {
        /** 为了用户体验,我们要尽量在用户选择市级城市后,默认选择一个区县级城市 */
        this.cac.country.id = this.country[0].id;
      }
    }
  }
}

最后再补上区县级下拉框:

<!-- 区县级下拉框 -->
<select [value]="cac.countryId" [(ngModel)]="cac.countryId" *ngIf="cac.cityType==0 && country.length > 0">
  <option *ngFor="let count of country" [value]="count.id">{{count.name}}</option>
</select>

到此为止,大功告成,再也不用去依赖别人的库了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Jquery Ajax学习实例7 Ajax所有过程事件分析示例
Mar 23 Javascript
基于jQuery的实现简单的分页控件
Oct 10 Javascript
SOSO地图JS画出标注和中心点以html形式运行
Aug 09 Javascript
jQuery插件Skippr实现焦点图幻灯片特效
Apr 12 Javascript
基于javascript实现根据身份证号码识别性别和年龄
Jan 22 Javascript
js+html5实现canvas绘制椭圆形图案的方法
May 21 Javascript
前端框架Vue.js中Directive知识详解
Sep 12 Javascript
ES6通过babel转码使用webpack使用import关键字
Dec 13 Javascript
node文件批量重命名的方法示例
Oct 23 Javascript
js实现input密码框显示/隐藏功能
Sep 10 Javascript
在Vue环境下利用worker运行interval计时器的步骤
Aug 01 Javascript
JavaScript 自定义html元素鼠标右键菜单功能
Dec 02 Javascript
微信小程序实现跟随菜单效果和循环嵌套加载数据
Nov 21 #Javascript
基于bootstrap写的一点localStorage本地储存
Nov 21 #Javascript
微信小程序实现下拉刷新和轮播图效果
Nov 21 #Javascript
基于 Vue.js 之 iView UI 框架非工程化实践记录(推荐)
Nov 21 #Javascript
微信小程序实现tab和swiper切换结合效果
Jul 17 #Javascript
微信小程序实现tab切换效果
Nov 21 #Javascript
jQuery实现所有验证通过方可提交的表单验证
Nov 21 #jQuery
You might like
PHP similar_text 字符串的相似性比较函数
2010/05/26 PHP
php写app用的框架整理
2019/09/29 PHP
nodejs中exports与module.exports的区别详细介绍
2013/01/14 NodeJs
jQuery实现的多选框多级联动插件
2014/05/02 Javascript
禁用Enter键表单自动提交实现代码
2014/05/22 Javascript
jQuery表单美化插件jqTransform使用详解
2015/04/12 Javascript
JavaScript中有关一个数组中最大值和最小值及它们的下表的输出的解决办法
2016/07/01 Javascript
vue快捷键与基础指令详解
2017/06/01 Javascript
JS获取子、父、兄节点方法小结
2017/08/14 Javascript
浅谈Angular路由守卫
2017/08/26 Javascript
原生JS实现小小的音乐播放器
2017/10/16 Javascript
pace.js和NProgress.js两个加载进度插件的一点小总结
2018/01/31 Javascript
Vue-cli Eslint在vscode里代码自动格式化的方法
2018/02/23 Javascript
说说Vuex的getters属性的具体用法
2019/04/15 Javascript
微信小程序实现原生步骤条
2019/07/25 Javascript
[05:40]DOTA2荣耀之路6:Wings最后进攻
2018/05/30 DOTA
Python初学时购物车程序练习实例(推荐)
2017/08/08 Python
将python图片转为二进制文本的实例
2019/01/24 Python
使用Windows批处理和WMI设置Python的环境变量方法
2019/08/14 Python
Python 格式化打印json数据方法(展开状态)
2020/02/27 Python
Marlies Dekkers内衣法国官方网上商店:国际知名的荷兰内衣品牌
2019/03/18 全球购物
曼城官方网上商店:Manchester City
2019/09/10 全球购物
美国沃尔玛网上超市:Walmart
2020/08/14 全球购物
瑞典最大的儿童用品网上商店:pinkorblue.se
2021/03/09 全球购物
叙述DBMS对数据控制功能有哪些
2016/06/12 面试题
.net软件工程师应聘上机试题
2015/03/10 面试题
本科生详细的自我评价
2013/09/19 职场文书
自我鉴定的范文
2013/10/03 职场文书
动物学专业毕业生求职信
2013/10/11 职场文书
联谊会主持词
2014/03/26 职场文书
优秀三好学生事迹材料
2014/08/31 职场文书
2015年大学迎新晚会总结
2015/07/16 职场文书
青少年法制教育心得体会
2016/01/14 职场文书
与Windows10相比Windows11有哪些改进?值不值得升级?
2021/11/21 数码科技
详解NumPy中的线性关系与数据修剪压缩
2022/05/25 Python
Mysql数据库group by原理详解
2022/07/07 MySQL