以省市区数据为例,组件成果如下:

技术亮点:

1.联合前后端通信,实现热更新式动静渲染数据2.利用setter,getter在组件中设置拜访器属性3.利用事件侦听,抛发实现级联成果4.实现自定义组件构造及款式

开发思路:

1.ajax申请:    1)页面初始化申请只申请省级数据,且整个渲染及交互过程中省级数据接口只会申请一次。    2)回调函数loadHandler中:判断本次ajax申请是哪个接口,如果是申请省级数据,则当省级数据获取后,利用组件实例化对象的setData办法,渲染省级组件,同时级联式去申请市级,县级的数据并渲染;如果本次申请市级接口则只渲染市级,县级数据,省级数据不变。    3)给组件绑定click侦听事件,当点击组件时抛发数据,携带点击的组件名及以后选中的参数;同理利用上述2)中的形式判断点击的是哪一级的数据,从而选择性申请市级,县级数据或者只申请县级数据2.setter,getter:给组件中的bool设置为拜访器属性,当点击事件触发时,实现bool值取反,同时ul列表款式绑定bool值实现动静扭转

组件代码如下:

import Component from "./Component.js";//该组件的超类,次要作用是申明了elem属性为div元素,并创立appendTo插入指标页面指定的dom元素中的办法import Utils from "./Utils.js";// 公共办法,次要调用其中 Utils.addCSS办法将款式退出指标页面的样式表中export default class Label extends Component{  list;  _bool = false;//拜访器属性:setter和getter  styleBool = false;  name;  constructor(_name) {    super();    this.name = _name;    this.elem.className = "dropup";    // 初始化创立组件时,只会给组件设置css款式及侦听元素的点击事件    this.elem.addEventListener("click", (e) => this.clickHandler(e));    // 渲染组件款式    this.setStyle();  }  render() {    // 渲染组件次要DOM构造    this.elem.innerHTML = "";    this.elem.innerHTML = `            <div class="show">          ${this.list[0]}        </div>        <ul class="ul1 ul2">          ${this.list.reduce(function (value,item) {            value += "<li>" + item + "</li>";            return value;           },"")}        </ul>  `  }  clickHandler(e) {    this.bool = !this.bool;    if (e.target.nodeName === "LI") {      this.elem.children[0].textContent = "";      this.elem.children[0].textContent = e.target.textContent;      // 抛发事件时携带数据,以后展现的是哪条数据,以及属于哪一级      var evt=new Event("change");      evt.data = this.elem.children[0].textContent;      evt.name = this.name;      this.dispatchEvent(evt);    }  }  setData(_list) {    this.list = _list;    this.render();    this.setStyle();    this.bool = false;  }  set bool(value){    if (value) {        this.elem.children[1].className = "ul1";      } else {      this.elem.children[1].className = "ul1 ul2";      }      this._bool=value;  }  get bool(){      return this._bool;   }  setStyle() {    if (this.styleBool) return;    Utils.addCSS(".dropup", {      width: "120px",      height: "30px",      lineHeight: "30px",      borderRadius: "4px",      border: "1px solid  rgba(0,0,0,.15)",      userSelect: "none",      textAlign: "center",      float: "left",      marginLeft:"10px",    });    Utils.addCSS(".ul1", {      listStyle: "none",      padding: "0",      border: "1px solid rgba(0,0,0,.15)",      borderRadius: "4px",      boxShadow: "0 6px 12px rgba(0,0,0,.175)",      margin: "2px 0 0",      fontSize: "14px",      textAlign: "left",      transition: "all 0.2s",      transitionProperty:"max-height",      maxHeight: "500px",      overflow: "auto",    });    Utils.addCSS(".ul2", {      maxHeight: "0px",      border: "none",    });    Utils.addCSS("li", {      padding: "0px 10px",    });    Utils.addCSS("li:hover", {      backgroundColor: "rgba(0,0,0,0.15)",    });    this.styleBool = true;  }}

主页面js局部代码如下:

    import Label from "./js/Label.js"    // 须要展现的省市县及源数据    var provinceArr,cityArr,countyArr;    // 省市区的实例化对象    var province,city,county;    init();    function init(){      render();//渲染出省市区的组件对象      ajax("province");//初始化申请省一级数据,从而触发级联反馈,loadhandler中申请市,区一级数据      // 整个过程中province只调用一次    }    function render(){      //创立省市区组件时不增加数据,对立在失去数据后,用setData增加数据渲染组件      province=new Label("province");      province.addEventListener("change",changeHandler);      province.appendTo(".setPos");      city=new Label("city");      city.appendTo(".setPos");      city.addEventListener("change",changeHandler);      county=new Label("county");      county.appendTo(".setPos");      county.addEventListener("change",changeHandler);    }    function changeHandler(e){      switch (e.name){        case "province":          // 点击省一栏时,市,县两级都要变          // 调用ajax申请市的接口,从而触发loadhandler中的联级反馈          ajax("city", {            province: e.data          });          break;        case "city":          // 点击市一栏时,县级须要变          // 以后状态下省一级的展现数据          var curProvince = province.elem.firstElementChild.textContent;          // 调用ajax申请县的接口,从而触发loadhandler中的联级反馈          ajax("county", {            province: curProvince,            city: e.data          });          break;      }    }    function ajax(name,data){      var xhr = new XMLHttpRequest();      xhr.addEventListener("load", loadHandler);      switch (name) {        case "province"://申请省份,加载第一层的数据          xhr.open("POST", "http://服务端接口url/province");          break;        case "city"://申请市级,加载第二层数据          xhr.open("POST", "http://服务端接口url/city");          break;        case "county"://申请县级,加载第三层数据          xhr.open("POST", "http://服务端接口url/county");          break;      }      data === undefined ? xhr.send() : xhr.send(JSON.stringify(data));    }    function loadHandler(e){        var xhr=e.currentTarget;        xhr.removeEventListener("load",loadHandler);        // 通过剪切responseURL获取申请的type接口类型        var type=xhr.responseURL.trim().split("?")[0].split("\/").pop();        var sourceData=JSON.parse(xhr.response);        switch(type){          case "province":            //当发现申请的是省级数据时,将省一级的数据渲染到组件上,同时须要去申请市一级的数据            provinceArr = sourceData;            ajax("city", {              "province": provinceArr[0]            });            province.setData(provinceArr);            break;          case "city":            // 当发现申请的是市级数据即市级数据须要更新,则将市一级的数据渲染到组件上,同时须要去申请县一级的数据            cityArr = sourceData;            var curProvince=province.elem.firstElementChild.textContent.trim();            ajax("county", {              "province": curProvince,              "city": cityArr[0]            });            city.setData(cityArr);            break;          case "county":            // 当发现是申请县一级数据时,间接将失去的数据渲染到组件上            countyArr = sourceData;            county.setData(countyArr);        }    }

接口文档如下:

省级数据:

申请形式:POST

申请地址:http://服务端接口url/province

申请参数格局:无

返回参数格局:

{  "res":["北京", "上海", "河北", "山西", "内蒙古"]}

市级数据:

申请形式:POST

申请地址:http://服务端接口url/city

申请参数格局:

{  "province": "北京"}

返回参数格局:

{  "res":["北京"]}

县级数据:

申请形式:POST

申请地址:http://服务端接口url/county

申请参数格局:

{    "province": "北京",    "city": "北京"}

返回参数格局:

{  "res":["东城区", "西城区", "崇文区", "宣武区", "朝阳区", "丰台区", "石景山区", "海淀区", "门头沟区", "房山区", "通州区", "顺义区", "昌平区", "大兴区", "平谷区", "怀柔区", "密云县", "延庆县", "其余"]}