代码优化及修正说明,新增两个功能,第一、指定parentId[用于筛选对应数据的根节点数],第二、返回所选择的数据数据及创建的class名称[用于重新绑定点击事件]。代码实例及创建代码如下:

 <!--地址信息--><div><span><i>*</i>地址信息:</span><input type="text" style="cursor: default;" class="choiceAddress" placeholder="请选择省市区"readonly="readonly"v-bind:data-id="shippingAddressItem.ShowAreaId"v-bind:data-assign="shippingAddressItem.ShowAreaId=='-1'?0:1" data-isclick="0":value="shippingAddressItem.ShowArea"></div>
 //#region 创建省份市区选择$.getJSON("../json/region.json", function (result) {var tempArray = eval(result);that.cachAddress = tempArray;});$.ajax({type: "GET",url: $.stringFormat("{0}/Public/getALLPlace", $.cookie("path")),async: true,success: function (result) {var jsonData = eval("(" + result + ")").data;that.address = jsonData;that.linkageObj = new Linkage({arr: that.address,containerClass: ".choiceAddress",isConsiderParent: false,isAddWidth: true,addWith: 7,returnSelectValue: function (data) {var result = "";var lastAreaText = "";//最后的地址文本data.map(function (item) {result += $.stringFormat("{0} ", item.Name);lastAreaText = item.Name;})that.shippingAddressItem.ShowArea = result;that.selectShowArea = data;that.cachAddress.map(function (item) {if (item.Name == lastAreaText) {that.shippingAddressItem.ZipCode = item.ZipCode;return false;}})},returnClass: function (clsName) {that.linkageClass = clsName;}})}});//#rendregion
that.linkageObj.showSelectInfoPane(that.linkageClass);此代码是重新创建绑定数据,注意我是结合vue开发使用的,具体大家看js源码自行扩展

新的下载地址

以上部分是新增优化内容,以下部分是旧说明内容


今天我们要讲的是如何利用jQuery仿京东收获地址,我们涉及的主要知识点为数组遍历,函数封装。按照惯例,我们在讲功能实现之前,先看看我们的效果展示图,图一为信息接收栏,图二为点击信息接收栏下拉选择,该结构类似于combobox。

图1 信息接收栏

图2 信息选择栏

结构分为两部分,文本选择框input,因为我们这边为了方便给input赋值之后能够模拟正常的点击效果,我们这边的input需要定义data-*类型数据,实例代码如下:

<input type="text" name="msg" readonly="readonly" id="msg" placeholder="请选择门店/部门/团队" data-id="854D87EFB26A04B8"data-assign="1" data-isclick="0"/>

上方的代码data-*对应的值代码当前input通过数据赋值,因此点击的时候将会获取对应的id、assign、isclick来判断是否需要模拟点击,默认情况下data-id="-1" data-assign="0" data-isclick="0"。同时我们定义的json返回类型数据为:

{ID: "BB47D6C7D2EB2EAC",ParentId: "-1",NavName: "03万达店"},

为了方便大家了解整个设计过程,我先解释我们如何实现反向模拟点击。整体的设计思路如下:给对应的input添加备注,是否是赋值的如果是赋值的,获取当前的ParentId,然后根据ParentId来获取具有上下级结构的数据源,同时将当前原始的对象添加的缓存数据源中。由于我们这边的li元素的class定义为我们对应的ID,因此我们遍历li判断对应的class是否和我们缓存数组(下面用Cache来代表我们的缓存数组)第一个元素ID相等,如果相等那么模拟点击,同时对于Cache移除已经模拟点击的数据。对应的代码如下:

1、获取input对应data("id")值的对象,注:return true相当于continue;return false相当于break;

 /*** 获取当前指定ID的ParentId* @param {Object} arr 数据源* @param {Object} id 当前数据ID*/SelectParentId = function (arr, id) {var obj;$(arr).each(function (index, item) {if (item.ID == id) {obj = item;return false;//退出整个循环 }})return obj;}

2、获取具有层级结构数据,这边采用递归调用的方法来获取对应的数据,代码中的ParentJson为上述所说的Cache。

/*** 获取当前元素上级数据集合,用于反向模拟效果* @param {Object} oldArr 数据集* @param {Object} pid 父节点Id*/SelectParentData = function (oldArr, pid) {oldArr.map(function (item) {if (item.ID == pid) {var obj = {ID: item.ID,ParentId: item.ParentId,NavName: item.NavName}SelectParentData(oldArr, item.ParentId);ParentJosn.push(obj);}})}

预备功能函数都创建完了,我们现在可以执行下一步操作,模拟点击事件处理。我们给input绑定个点击事件,对当前点击对象的备注属性isclick置为1,方便接下来的判断操作,具体代码写法为$(this).data("isclick", "1");第二步则为判断当前点击的input对象的assign值是否为1,如果是1的话代表当前是赋值的,需要模拟点击。除此之外,判断id是否为"-1"如果是"-1"代表该值为默认值,同样不需要模拟点击操作。

先获取当前input在数据源的元素对象,var obj = SelectParentId(jsonData, Id)这边的jsonData为数据源;然后获取上级结构数据SelectParentData(jsonData, obj.ParentId);同时将obj追加到Cache中 ParentJosn.push(obj);最后遍历查询li元素[这边需要判断Cache是否有值],实现代码如下:

if (ParentJosn.length > 0) {//判断当前获取的具有上级机构的数组长度大于0$(".contentsMain .contents-center ul").find("li").each(function () {if (ParentJosn.length > 0) {if ($(this).hasClass(ParentJosn[0].ID)) {RemoveArray(ParentJosn, ParentJosn[0].ID);$(this).click();return true;}}})}

上方的代码中的RemoveArray为删除数组数据,完整代码如下,我们采用splice对数据进行删除操作,splice() 方法可删除从 index 处开始的零个或多个元素,并且用参数列表中声明的一个或多个值来替换那些被删除的元素。如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组。

/*** 删除数据* @param arr 数据源* @param id 元素对应的Id* @constructor*/RemoveArray = function (arr, id) {var tempIndex = 0;$(arr).each(function (index, item) {if (item.ID == id) {tempIndex = index;return true;}})arr.splice(tempIndex, 1);}

我们当前模拟点击的只是其中一个div li元素而已,因为我们点击的是li元素,我们的li元素点击之后是会查找是否含有下一级数据,如果含有下一级元素继续创建上述结构的HTML。因此我们需要在创建ul-li元素之后判断是否需要模拟点击,上述所说的input备注主要用处也是在这边体现。我们需要判断input是否是赋值的同时是否是点击触发的,然后执行上述操作,这边不再赘述,直接贴代码。

 //#region 判断方向结构数据是否有值,如果有值执行下一步操作if ($("#msg").data("assign") == "1" && $("#msg").data("isclick") == "1") {ulHtml.find("li").each(function () {if (ParentJosn.length > 0) {if ($(this).hasClass(ParentJosn[0].ID)) {RemoveArray(ParentJosn, ParentJosn[0].ID);$(this).click();return true;}} else$("#msg").data("assign", 0);})}//#endregion

至此我们的反向模拟操作就此结束,现在让我们回过头来看看我们正常操作代码如何实现。步骤是先创建代码,然后创建样式最后绑定对应的点击事件。考虑到我们页面上可能会创建多个类似的功能页面,我们这边以时间戳来创建class名称。对应创建html的写法如下:

 //#region 定义变量var self = this,_config = self.config,_cache = self.cache;var _Linkage = new Date().getTime();_Linkage = 'Y' + _Linkage;//#endregion//#region 创建divvar divHtml = $('<div class="contentsMain ' + _Linkage + '">' +'    <!--顶部选择门店/部门/团队类似结构数据-->' +'    <div class="contents-top"></div>' +'    <!--筛选-->' +'    <div class="contents-center"></div>' +'    <!--底部操作-->' +'    <div class="contents-bottom">' +'        <span>点击完成即为选择完成</span>' +'        <span class="ok">完成</span>' +'        <span class="cancel">取消</span>' +'    </div>' +'</div>');$("body").append(divHtml);//#endregion

当前创建的是大体容器,我们还需要创建firstPage的ul-li元素,同时考虑到我们创建的html是具有共用属性,因此我们需要创建一个方法。firstPage的页面ui-li元素数据是根节点数据,每点击li元素会以当前元素的id去获取下一级数据。获取指定ParentId数据实现方法代码如下:[注:贴出的代码是封装在js的写法]

 /*** 获取指定parentId的同级数据* @param pid 父节点ID* @return {Array} 返回parentId相同的数据集合*/selectEquativeData:function (pid) {var self = this,_config = self.config,_cache = self.cache;var tempData = [];//缓存数据$(_config.arr).each(function (index, item) {if (item.ParentId == pid) {var obj = {ID: item.ID,ParentId: item.ParentId,NavName: item.NavName}tempData.push(obj);}});return tempData;}

创建选择信息栏,首先我们移除contents-center所有的选中状态,判断当前parentId为class名称的div是否创建过,如果创建过,直接元素清除,反之创建。创建ul-li的时候同时创建切换标签页,对ul-li事件处理的时候需要判断当前点击对象是不是已经是选中状态,如果是直接执行切换操作,如果不是则对ul-li样式变化进行操作。第一步对li移除所有的选中效果;第二步暂存当前点击的class,因为待会将创建一个"selected"class名称;第三步获取点击的对象数据 对应的标签页及内容进行移除操作;第四步数据查找,如果存在继续递归创建,反之slideUp();具体代码实现如下:

 var contents = $("." + linkageClass + " .contents-center");$(contents).find("div").removeClass("actived");//移除所有的选中状态var boxClassName = pid == "-1" ? "firstPage" : pid;var length = 0;//判断当前的pid是否创建过,如果是创建过,直接元素清除contents.find("div").each(function () {if ($(this).hasClass(boxClassName))length++;})var box;//定义变量存储//#region 内容容器判断if (length > 0) {box = $("." + linkageClass + " .contents-center ." + boxClassName);box.empty();} else {//未创建//#region 切换标签页// 创建切换标签页var spanHtml = $("<span  class='" + boxClassName + " selected' data-selectid='" + boxClassName + "' data-id='-1'>请选择</span>")$("." + linkageClass + " .contents-top").append(spanHtml);//切换标签页事件绑定spanHtml.bind("click", function () {$("." + linkageClass + " .contents-center").find("div").removeClass("actived");var clsName = $(this).data("selectid");$("." + linkageClass + " .contents-center ").find("div").each(function () {if ($(this).hasClass(clsName))$(this).addClass("actived");})$(this).parent().find("span").removeClass("selected");$(this).addClass("selected");})//#endregion//#region 创建内容容器boxClassName += " actived";box = $("<div class='" + boxClassName + "'></div>")$(contents).append(box);//#endregion}//#endregion//#region 创建ul-li及事件绑定处理var ulHtml = $("<ul></ul>");box.append(ulHtml);$(arr).each(function (index, item) {var liHtml = $("<li class='" + item.ID + "' data-parentid='" + item.ParentId + "' data-index='" + index + "'>" + item.NavName + "</li>");ulHtml.append(liHtml);//绑定点击事件liHtml.bind("click", function () {var ParentId = $(this).data("parentid");var spanClass = ParentId == "-1" ? "firstPage" : ParentId;//获取点击对象的class//#region 当前点击对象为已经创建对象if (!$(this).hasClass("selected")) {//当前点击的对象不是已经选中的元素//#region  对ul-li样式变化进行操作$(this).parent().find("li").removeClass("selected");//移除所有的选中效果var classId = $(this).attr("class");//暂存当前点击的class,因为待会将创建一个"selected"class名称$(this).addClass("selected");//#endregion//#region  获取点击的对象数据 对应的标签页及内容进行移除操作$("." + linkageClass + " .contents-top ." + spanClass).text($(this).text());$("." + linkageClass + " .contents-top ." + spanClass).data("id", classId);$("." + linkageClass + " .contents-top ." + spanClass).nextAll().remove();//将当前元素后面的所有元素进行移除$(this).parent().parent().nextAll().remove();//移除整个div//#endregion//#region 数据查找,如果存在继续递归创建var tempData = self.selectEquativeData(classId);//查找当前点击对象下属所有数据if (tempData != undefined && tempData.length > 0) {$("." + linkageClass + " .contents-top ." + spanClass).removeClass("selected");self.createHtml(linkageClass, tempData, classId);} else {var selectText = "";$("." + linkageClass + " .contents-top").find("span").each(function () {if ($(this).text().trim() != "请选择")selectText += $(this).text().trim() + " ";})$(_config.containerClass).val(selectText);if ($("." + linkageClass + " .contents-top .selected").text() == "请选择")$(_config.containerClass).data("id", $("." + linkageClass + " .contents-top .selected").prev().data("id"));else$(_config.containerClass).data("id", $("." + linkageClass + " .contents-top .selected").data("id"));$("." + linkageClass).slideUp(300);}//#endregion}//#endregion//#region 点击的是已经选中的元素 直接执行切换的操作else {$("." + linkageClass + " .contents-top ." + spanClass).next().click();}//#endregion})})//#endregion

事件绑定分为两部分第一部分是对input框进行判断,第一部分是对我们创建的元素进行绑定。为了让我们创建的选择框实时贴合在input的下方且宽度与父容器保持一致,我们注册了窗体改变大小事件。当窗体改变的时候我们更改新建div的left、top以及width,由于我们创建的信息选择框会存在一点的误差,因此我们创建了以及参数方便我们界面开发者调整解决误差。这三个参数分别是:isConsiderParent默认值为false(是否需要考虑点击对象的父容器,通常用于计算宽度)、isAddWidth默认值为false(是否需要给对应的下拉信息框追加宽度)、addWith默认值为0(追加的宽度大小,当isAddWidth为true时才生效)。

调用方法:

 new Linkage({arr: jsonData,//数据源containerClass: ".input-belong",//文本输入框isConsiderParent: false,//由于默认值为false 该参数可不写isAddWidth: false,//由于默认值为false 该参数可不写addWith: 0,//当isAddWidth为false时,该值可不传递});//由于默认值为false 该参数可不写addWith: 0,//当isAddWidth为false时,该值可不传递});

至此我们的功能已经介绍完毕。完整代码下载地址

用jQuery仿京东收货地址相关推荐

  1. Android仿京东收货地址

    Android仿京东三级联动收货地址 1.在本地新建assets目录,存放三级联动json数据,取本地json数据作为数据源 String data = com.miles.zcstc.fingerd ...

  2. 仿京东收货地址三级联动

    声明 我没有用tabLayout(pageSlidingTabStrip) + viewpager  + fragment 如果用上面的方法实现 更加简单         我用的是  一个listvi ...

  3. 基于uni-app实现京东收货地址

    本文是用uni-app来实现收货地址城市选择,如果你想要用jquery实现相同效果可以查看我之前写的文章,用jQuery仿京东收货地址.本次的功能实现相比用jquery会比较简单,关键在于我们对缓存数 ...

  4. html5手机端三级联动城市选择代码,省市县三级联动(jQuery手机端收货地址选择地区代码)...

    [实例简介] [实例截图] [核心代码] jQuery手机端收货地址选择代码 - 站长素材 默认调用 所在地区: 设置默认值 所在地区: /** * 默认调用 */ !function () { va ...

  5. android 京东收货地址,手机京东商城怎么添加收货地址?

    想必有很多人都使用过手机京东购物,购物就需要一个收货地址,在手机京东上,具体怎么添加一个收货地址呢?或者说,由于某些特殊的原因,比如帮别人买东西,或者自己不在原来的地方住了,需要修改原来的收货地址,这 ...

  6. php商城手机端省市显示,jQuery仿手机京东商城收货地址城市选择

    jQuery仿手机京东商城收货地址城市选择 js代码 /** * 默认调用 */ !function () { var $target = $('#J_Address'); $target.cityS ...

  7. 39 Flutter仿京东商城项目 收货地址列表、增加 修改收货地址布局、弹出省市区选择器...

    加群452892873 下载对应39课文件,运行方法,建好项目,直接替换lib目录 pubspec.yaml city_pickers: ^0.1.22 AddressAdd.dart import ...

  8. ionic4.x仿京东 - 10.3.4.收货地址-修改默认收货地址、显示默认收货地址

    一.修改默认收货地址 1.接口信息 请求方式:post 地址:域名/api/changeDefaultAddress 传参说明: 参数 说明 备注 uid 用户 id 必传 sign 签名 验证地址是 ...

  9. 方便代理下单的EcStore收货地址一键分析插件,同时支持淘宝/京东/一号店

    使用EcStore开展分销的网站,代理需要经常代客下单,每个客户收货地址都不同,要选择和填写多个内容才能完成地址输入:省.市.区.详细地址.收货人姓名.手机电话等,非常麻烦,也容易输入错误. 安装Ec ...

最新文章

  1. HDU1874(SPFA算法)
  2. 安装配置Kali虚拟机----linux----kali
  3. 笔记-项目成本管理-估算成本的步骤
  4. 构建可扩展的思科互联网络---单区域OSPF
  5. 基于java的音乐网站的设计与实现
  6. Python经典前端框架:Django,第一天【Django环境搭建】
  7. 简易PDF电子书书签制作
  8. 【STM32F042】使用NTC热敏电阻实现温度测量
  9. App、小程序、H5的区别
  10. acme申请证书报错:Please update your account with an email address first.的修复方法
  11. 为了让机器听懂“长篇大论”,阿里工程师构建了新模型
  12. 惠普m154a状态页_惠普m154a感叹号闪烁
  13. 如何通过 WhatsApp 开展营销活动?
  14. [USA]办理美国签证,被Check
  15. 双屏显示例程C#例程
  16. 爬取近千张女神赫本的美照,做成网站并给其中的黑白照片上色,好玩!
  17. python地铁查询系统_基于图结构实现地铁乘坐线路查询
  18. 自定义的串口通信协议
  19. 浏览器服务器三层系统结构,Browser/Server系统的三层体系结构
  20. 三大运营商争夺iPhone,活体免费

热门文章

  1. latex 参考文献显示问号_VS Code + LaTeX
  2. 不知道拍照识别文字的软件哪个好?这3款软件很实用
  3. 数据库SQLserver(课本)
  4. python switch to frame_Switch to Frame
  5. 如何删除MacOS自带的输入法的自造词(Catalina)
  6. 前端大屏展示框架搭建(一)
  7. 2023年美赛C题Wordle预测问题二建模及Python代码详细讲解
  8. 办理《北京市工作居住证》各项变更须提交材料
  9. Linux的命令行无法粘贴
  10. 使用线性神经网络实现逻辑与和逻辑异或(一)