原生微信小程序中案例--仿boss区域树选择列多选功能

1. 需求描述:

区域三级列表, 有添加,编辑,删除功能。

  1. 选择父级分类,其下子类全部选中,当前分类后加标志显示字样
  2. 取消选中子类,其父类分类后标志显示选中数量
  3. 若子类全部选中,除当前父类标志是字外,显示页面只显示当前父类
  4. 清除则清空选中结果
  5. 后台提交数据传参说明:
    • 如果子类全部选择,只传父类code
    • 如果子类没有全部选择,传父类code+子类code

示例:

  1. 选择数据
  • 河北省下:
    1.石家庄市子类全部选中,
    2.唐山市子类选择桥西区、长安区
    页面显示:
    - 河北 石家庄
    - 河北 唐山市 桥西区
    - 河北 唐山市 长安区
  • 山西省:(假设山西省下只有大同市和太原市)
    1. 太原市子类全部选中
    2. 大同市子类全部选中
    页面显示:
    - 山西省
  1. 传输参数
	data: [{one:130000, two: '130100'},{one:130000, two: '130200', three: '130201'},{one:130000, two: '130200', three: '130202'},{one:140000}]

2. 效果图:

描述

3. 代码

  1. 主页面:show.wxml
<!-- 选择地区 -->
<view class="recycle-container"><view class="title">选择地区<view class="option-btn" bind:tap="toEditArea" wx:if="{{areaList.length}}"><view class="option-icon">+</view><text class="option-text">去编辑</text></view></view><view class="explain">选择您的地区</view><view class='msgHint-content max-height'><view class="msgHint-content-item" wx:for="{{areaList}}" wx:key="id"><view class="account-content">{{item.zone_name}}</view><text class="option-text" data-_id="{{item.id}}"bind:tap="delArea">删除</text></view></view><!-- 去添加 --><view wx:if="{{!areaList.length}}" class="plus-container" bind:tap="addArea"><view class="plus-content">+</view><view class="plus-text">去添加</view></view><!-- 操作 --><view class="msgHint-content" wx:else></view>
</view>
  1. 添加区域页面area.wxml
<!-- 内容区 -->
<view class="area-container"><!-- 省 --><scroll-view class="white-container scroll-container" scroll-y="{{true}}" enhanced="{{true}}"show-scrollbar="{{false}}"><view wx:for="{{areaList}}" wx:key="index"data-idx="{{index}}" class="scroll-item {{ index === provinceCurrentIdx ? 'left-container': ''}} {{ item.is_choice ? 'scroll-item-active': ''}}"bind:tap="provinceClick">{{ item.name }}<view class="item-sign" wx:if="{{item.signName}}">{{item.signName}}</view></view></scroll-view><!-- 市 --><scroll-view class="white-container scroll-container" scroll-y="{{true}}" enhanced="{{true}}"show-scrollbar="{{false}}"><view wx:for="{{cityList}}" wx:key="index"data-idx="{{index}}" class="scroll-item {{ index === cityCurrentIdx ? 'left-container': ''}} {{item.is_choice ? 'scroll-item-active' : ''}}"bind:tap="cityClick">{{ item.name }}<view class="item-sign" wx:if="{{item.signName}}">{{item.signName}}</view></view></scroll-view><!-- 区县 --><scroll-view class="white-container scroll-container"scroll-y="{{true}}" enhanced="{{true}}"show-scrollbar="{{false}}"><view wx:for="{{townList}}" wx:key="index"data-idx="{{index}}" class="scroll-item {{ item.is_choice ? 'scroll-item-active': ''}}"bind:tap="townClick">{{ item.name }}</view></scroll-view>
</view>
<!-- 底部 -->
<view class="footer"><view class="options-container"><button class="cancel-btn" bind:tap="cancel">清除</button><button class="sure-btn" type="primary" bind:tap="sure">确定</button></view>
</view>
  1. 区域操作页面:area.js:
const app = getApp()
const {throttle} = require('../../../utils/throttle')
Page({/*** 页面的初始数据*/data: {// 省数据areaList: [],// 省当前选中索引值provinceCurrentIdx: 0,// 市数据cityList: [],// 市当前选中索引值cityCurrentIdx: 0,// 区县数据townList: [],},// 清除cancel(){const {areaList, cityList, townList} = this.dataareaList.map(one => {one.isSelect = 0one.signName = ''if(!one.children || !one.children.length) returnone.children.map(two => {two.isSelect = 0two.signName = ''if(!two.children || !two.children.length) returntwo.children.map(three => {three.isSelect = 0})})})cityList.map(item=> {item.isSelect = 0; item.signName = ''})townList.map(item=> item.isSelect = 0)this.setData({areaList,cityList,townList})},// 注册节流事件throttle(){},// 点击确定,调取节流sure(){this.throttle()},// 保存save(){const selectArea = this.data.areaList.filter(item => item.isSelect)if(!selectArea.length){return wx.showToast({title: '请选择地区',icon: 'none'})}// 处理参数并返回结果const params =this.getParams(selectArea)// todo 可注释请求,查看结果wx.request({url: "",header: {},data: {data: params },method: 'POST',success: function(res) {}})},getParams(arr){const params = []arr.map(one => {// 若省无子集if(!one.children || !one.children.length){return params.push({one: one.code})}const twoAreas = one.children.filter(item => item.isSelect)const isAll = twoAreas.every(two => (two.signName+'').localeCompare('全') === 0)if((twoAreas.length === one.children.length) && isAll){return params.push({one: one.code})}twoAreas.map(two => {// 选中的市若无子集if(!two.children || !two.children.length){return params.push({one: one.code, two: two.code})}const threeAreas = two.children.filter(item => item.isSelect)if(threeAreas.length === two.children.length){return params.push({one: one.code, two: two.code})}// 区县集threeAreas.map(three => {params.push({one: one.code, two: two.code, three: three.code})})})})return JSON.stringify(params)},/*** 生命周期函数--监听页面加载*/onLoad(options) {this.throttle = throttle(this.save, 2000)},onShow() {this.getArea()},// 获取地区getArea(){const _this = this// todo 可注释请求,只做虚拟数据操作// _this.valuation(datalist)// _this.initShow(datalist)wx.request({url: "",header: {},data: {},method: 'POST',success: function(res) {if (res.statusCode == 200) {if(res.data.code == 200){const arr =  [...数据]const datalist = arr.map(item => {item.signName = ''return item})// 回显地区_this.valuation(datalist)_this.initShow(datalist)} else {wx.showToast({title: res.data.msg,icon: 'none'})}}}})},// 地区回显valuation(datalist){const selectList = datalist.filter(item=> item.isSelect)if(!selectList.length){return}selectList.map(one=>{if(!one.children || !one.children.length){one.signName = '全'return}const selectTwo = one.children.filter(two => two.isSelect)one.signName = selectTwo.length === one.children.length? '全': selectTwo.lengthone.children.map(two => {if(!two.children || !two.children.length){two.signName = '全'return}const selectThree = two.children.filter(three => three.isSelect)two.signName = selectThree.length === two.children.length? '全': selectThree.length})})},// 定位点击省市区并初始加载initShow(datalist){const provinceCurrentIdx = datalist.findIndex(item => item.isSelect)if(provinceCurrentIdx === -1){return this.setData({areaList: datalist})}if(!datalist[provinceCurrentIdx].children && !datalist[provinceCurrentIdx].children.length){return this.setData({areaList: datalist,provinceCurrentIdx})}const cityList = datalist[provinceCurrentIdx].childrenconst cityCurrentIdx = cityList.findIndex(item => item.isSelect)if(cityCurrentIdx === -1){return this.setData({areaList: datalist,provinceCurrentIdx,cityList})}if(!cityList[cityCurrentIdx].children && !cityList[cityCurrentIdx].children.length){return this.setData({areaList: datalist,provinceCurrentIdx,cityList,cityCurrentIdx})}const townList = cityList[cityCurrentIdx].childrenthis.setData({areaList: datalist,provinceCurrentIdx,cityList,cityCurrentIdx,townList})},// 点击省provinceClick(e){const { idx } = e.target.datasetconst { areaList, provinceCurrentIdx } = this.data// 切换省,则默认选中if(provinceCurrentIdx == idx){areaList[idx].isSelect = areaList[idx].isSelect ? 0  : 1this.setChioce(areaList[idx])this.setSign(areaList[idx])} else {if(!areaList[idx].isSelect){areaList[idx].isSelect = 1this.setChioce(areaList[idx])this.setSign(areaList[idx])}}this.setData({areaList: areaList,provinceCurrentIdx: idx,cityList: [],cityCurrentIdx: 0,townList: [],})this.getChildArea(1)this.getChildArea(2)},// 点击市cityClick(e){const { idx } = e.target.datasetconst { areaList, cityList, cityCurrentIdx } = this.dataif(cityCurrentIdx == idx){cityList[idx].isSelect = cityList[idx].isSelect ? 0  : 1this.setChioce(cityList[idx])this.setParentChioce(cityList[idx])this.setSign(cityList[idx])} else {if(!cityList[idx].isSelect){cityList[idx].isSelect = 1this.setChioce(cityList[idx])this.setParentChioce(cityList[idx])this.setSign(cityList[idx])}}this.setData({areaList: areaList,cityList: cityList,cityCurrentIdx: idx,townList: [],})this.getChildArea(2)}, // 找下一级的地区getChildArea(level){const { areaList, provinceCurrentIdx, cityList, cityCurrentIdx } = this.dataswitch (level){case 1:if(areaList[provinceCurrentIdx].children){this.setData({cityList: areaList[provinceCurrentIdx].children})}break;case 2:if(cityList[cityCurrentIdx] && cityList[cityCurrentIdx].children){this.setData({townList: cityList[cityCurrentIdx].children})}break;}},// 切换--当前项子项选中与取消选中setChioce(data){if(!data.children) returndata.children.forEach(item => {item.isSelect = data.isSelectthis.setChioce(item)})},// 设置父元素选中setParentChioce(){let { areaList, provinceCurrentIdx, cityList } = this.dataareaList[provinceCurrentIdx].isSelect = 1// 设置市选中状态及角标const len = cityList.filter(item => item.isSelect).lengthif(!len){areaList[provinceCurrentIdx].isSelect = 0}},// 设置元素角标setSign(data){let { areaList, provinceCurrentIdx, cityList } = this.data// 设置当前元素角标提示if(data.isSelect){data.signName = '全'} else {data.signName = ''}// 关联其父角标提示if(data.parentId){const len = areaList[provinceCurrentIdx].children.filter(item => item.isSelect).lengthif(cityList.length === len){areaList[provinceCurrentIdx].signName = '全'} else {areaList[provinceCurrentIdx].signName = len}}// 关联其子角标提示if(data.children){data.children.forEach(item => {item.signName = data.isSelect ? '全' : ''})}},// 点击区县townClick(e){let { areaList, provinceCurrentIdx, cityList, cityCurrentIdx, townList } = this.dataconst { idx } = e.target.datasettownList[idx].isSelect = townList[idx].isSelect ? 0 : 1cityList[cityCurrentIdx].isSelect = 1areaList[provinceCurrentIdx].isSelect = 1// 设置市选中状态及角标const len = townList.filter(item => item.isSelect).lengthif(!len){cityList[cityCurrentIdx].isSelect = 0}if(cityList[cityCurrentIdx].children.length === len){cityList[cityCurrentIdx].signName = '全'} else {cityList[cityCurrentIdx].signName = len}// 设置省选中状态及角标const lenP = areaList[provinceCurrentIdx].children.filter(item => item.isSelect).lengthif(!lenP){areaList[provinceCurrentIdx].isSelect = 0}if(cityList.length === lenP){areaList[provinceCurrentIdx].signName = '全'} else {areaList[provinceCurrentIdx].signName = lenP}this.setData({areaList: areaList,cityList: cityList,townList: townList})},})
  1. 当然还加了一个节流操作:
// throttle.js
function throttle(func, limit) {  let lastFunc;  let lastRan;  return function() {  const context = this;  const args = arguments;  if (!lastRan) {  func.apply(context, args);  lastRan = Date.now();  } else {  clearTimeout(lastFunc);  lastFunc = setTimeout(function() {  if ((Date.now() - lastRan) >= limit) {  func.apply(context, args);  lastRan = Date.now();  }  }, limit - (Date.now() - lastRan));  }  };  
}
module.exports = {throttle
}
  1. 您可以拿测试数据测试:
    • code:唯一值
    • isSelect:表示选中,回显时记得更改,0表示未选择,1表示选择
    • parentId:父级code
    • parentName: 父级name
    • children: 子集
{"data": [{"code": "110000","isSelect": 0,"name":"北京","children": [{"code": "110100","isSelect": 0,"name": "北京","parentId": "110000","parentName": "北京","children": [ {"code": "110101","isSelect": 0,"name": "东城区","parentId": "110100","parentName": "北京"},{"code": "110102","isSelect": 0,"name": "西城区","parentId": "110100","parentName": "北京"},{"code": "110103","isSelect": 0,"name": "朝阳区","parentId": "110100","parentName": "北京"}],}]},{"code": "130000","isSelect": 0,"name":"河北","children": [{"code": "130100","isSelect": 0,"name": "石家庄市","parentId": "130000","parentName": "河北","children": [ {"code": "130101","isSelect": 0,"name": "桥西区","parentId": "130100","parentName": "石家庄市"},{"code": "130102","isSelect": 0,"name": "长安区","parentId": "130100","parentName": "石家庄市"},{"code": "130103","isSelect": 0,"name": "新华区","parentId": "130100","parentName": "石家庄市"}],},{"code": "130200","isSelect": 0,"name": "唐山市","parentId": "130000","parentName": "河北","children": [ {"code": "130201","isSelect": 0,"name": "桥西区","parentId": "130200","parentName": "唐山市"},{"code": "130202","isSelect": 0,"name": "长安区","parentId": "130200","parentName": "唐山市"},{"code": "130203","isSelect": 0,"name": "新华区","parentId": "130200","parentName": "唐山市"}],}]},{"code": "140000","isSelect": 0,"name":"山西","children": [{"code": "140100","isSelect": 0,"name": "太原市","parentId": "140000","parentName": "山西","children": [ {"code": "140101","isSelect": 0,"name": "小店区","parentId": "140100","parentName": "太原市"},{"code": "140102","isSelect": 0,"name": "迎泽区","parentId": "140100","parentName": "太原市"},{"code": "140103","isSelect": 0,"name": "万柏林区","parentId": "140100","parentName": "太原市"},{"code": "140104","isSelect": 0,"name": "尖草坪区","parentId": "140100","parentName": "太原市"},{"code": "140105","isSelect": 0,"name": "阳曲县","parentId": "140100","parentName": "太原市"},{"code": "140106","isSelect": 0,"name": "古交市","parentId": "140100","parentName": "太原市"}],},{"code": "140200","isSelect": 0,"name": "大同市","parentId": "140000","parentName": "山西","children": [ {"code": "140201","isSelect": 0,"name": "新荣区","parentId": "140200","parentName": "大同市"},{"code": "140202","isSelect": 0,"name": "平城区","parentId": "140200","parentName": "大同市"},{"code": "140203","isSelect": 0,"name": "云州区","parentId": "140200","parentName": "大同市"},]}]}]
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/3412.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对2023年图灵奖揭晓看法

2023年图灵奖揭晓&#xff0c;你怎么看&#xff1f; 2023年图灵奖&#xff0c;最近刚刚颁给普林斯顿数学教授 Avi Wigderson&#xff01;作为理论计算机科学领域的领军人物&#xff0c;他对于理解计算中的随机性和伪随机性的作用&#xff0c;作出了开创性贡献。这些贡献不仅推…

【stomp 实战】spring websocket源码分析之握手请求的处理

上一节【搭建一套websocket推送平台】我们通过一个项目&#xff0c;实现了一套推送平台。由于spring框架对于websocket的支持和stomp协议的良好封装&#xff0c;我们很容易地就实现了websocket的消息推送功能。虽然搭建这么一套推送系统不难&#xff0c;但是如果不了解其底层原…

Spring Cloud Alibaba Sentinel 使用

初识Sentinel Sentinel是阿里巴巴开源的一款微服务流量控制组件。官网地址&#xff1a; home | Sentinel 需要了解的概念 簇点链路 在学习 Sentinel 的使用之前&#xff0c;我们有必要首先了解一下簇点链路。当请求进入微服务时&#xff0c;首先会访Controller、Service、Ma…

赋能智慧校园!A3D数字孪生可视化,轻量又高效!

放假之后&#xff0c;学生们会逐步返学&#xff0c;大量人员出入校园&#xff0c;安全更是不容忽视&#xff0c;如何在短时间内对大批人员及设施进行智能监管&#xff1f;数字化转型是关键手段&#xff0c;我们可以融合线上线下数据&#xff0c;搭建3D立体的智慧校园&#xff0…

Unity 按下Play键后,Scene View里面一切正常,但是Game View中什么都没有 -- Camera Clear Flags的设置

问题如下所示。 最先遇到这个问题是我想用Unity开发一个VR 360-degree Image Viewer。在Scene View中可以看到球体&#xff0c;但是Game View什么都看不到。最后找到的原因是&#xff0c;我使用的shader是Skybox/Panorama&#xff0c; 需要把Main Camera的Clear Flags设置成Do…

hanoi塔

hanoi塔问题&#xff1a; 1.规则&#xff1a;一次移动一个盘子&#xff0c;小盘子压大盘子上面&#xff0c;有A、B、C三个柱子&#xff0c;A是起始放盘子的柱子&#xff0c;B是中间可以借助的柱子&#xff0c;C是最后放盘子的位置 2.简单思路&#xff1a; 如果有1个盘子&…

netsh int ipv4 show dynamicport tcp动态端口port设置

netsh int ipv4 show dynamicport tcp netsh int ipv4 set dynamicport tcp start4000 num10000

【Go语言快速上手(四)】面向对象的三大特性引入

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Go语言专栏⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Go语言知识   &#x1f51d;&#x1f51d; GO快速上手 1. 前言2. 初识GO中的结构…

JAVA毕业设计136—基于Java+Springboot+Vue的房屋租赁管理系统(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootVue的房屋租赁管理系统(源代码数据库)136 一、系统介绍 本项目前后端分离&#xff0c;分为管理员、用户、工作人员、房东四种角色 1、用户/房东&#xff1a; …

【网络安全】网络安全协议和防火墙

目录 1、网络层的安全协议&#xff1a;IPsec 协议族 &#xff08;1&#xff09;IP 安全数据报格式 &#xff08;2&#xff09;互联网密钥交换 IKE (Internet Key Exchange) 协议 2、运输层的安全协议&#xff1a;TLS 协议 3、系统安全&#xff1a;防火墙与入侵检测 1、网络…

数据结构篇其二---单链表(C语言+超万字解析)

目录 前言&#xff1a; 一、顺序表的缺点和链表的引入。 二、链表概述 实现一个简单的链表 空链表的概念 三、链表的功能实现 链表的打印 链表节点的创建 链表的头插&#xff08;自上而下看完分析&#xff0c;相信你会有所收获&#xff09; 头插的前置分析 传值调用和…

OSPF的LSA与特殊区域

Area区域概念 *一个区域维护一张LSDB&#xff0c;路由器详细的链路信息只在这个区域内传播 不是每一台路由器都需要了解所有外部目的地的详细信息 *OSPF网络的层次化设计 通过区域ID标识 骨干&#xff08; Backbone &#xff09;区域&#xff0c;必须是area 0(骨干区域…

Dos慢速攻击

这里写自定义目录标题 Dos慢速攻击 Dos慢速攻击 测试结果为“Exit status&#xff1a; No open connections left"&#xff0c;代表无此漏洞。 如果测试结束后connected数量较多&#xff0c;closed数量很少或0&#xff0c;说明之前建立的慢速攻击测试连接没有关闭&#…

书生·浦语 大模型(学习笔记-7)LMDeploy 量化部署 LLM-VLM 实践

目录 一、模型的部署 二、模型部署面临的问题 三、如何解决&#xff08;两种方法&#xff09; 四、LMDeploy相关知识 创建conda环境(漫长的等待) 五、使用LMDeploy与模型对话 六、设置最大KV Cache缓存大小 七、W4A16量化 八、客户端连接API服务器 一、模型的部署 二、…

NLP step by step -- 了解Transformer

Transformer模型 Transformer相关历史 首先我们先看一下有关Transformer模型的发展历史&#xff0c;下面的图是基于Transformer架构的一些关键模型节点&#xff1a; 图片来源于Hugging Face 图片来源于Hugging Face Transformer 架构 于 2017 年 6 月推出。原本研究的重点是…

Java面试八股之Java中为什么没有全局变量

Java中为什么没有全局变量 Java中没有传统意义上的全局变量&#xff0c;这是因为Java语言设计遵循面向对象的原则&#xff0c;强调封装性和模块化&#xff0c;以及避免全局状态带来的副作用。 封装性&#xff1a; 全局变量违反了面向对象编程中的封装原则&#xff0c;即隐藏对…

Spring Boot集成RabbitMQ快速入门Demo

1.什么是RabbitMQ&#xff1f; RabbitMQ是一款使用Erlang语言开发的&#xff0c;基于AMQP协议的消息中间件&#xff0c;作为一款优秀的消息系统&#xff0c;RabbitMQ有高并发、可扩展等优势&#xff0c;并适用于大型系统中各个模块之间的通信。 RabbitMQ的特点为&#xff1a; 持…

【白盒测试】单元测试的理论基础及用例设计技术(6种)详解

目录 &#x1f31e;前言 &#x1f3de;️1. 单元测试的理论基础 &#x1f30a;1.1 单元测试是什么 &#x1f30a;1.2 单元测试的好处 &#x1f30a;1.3 单元测试的要求 &#x1f30a;1.4 测试框架-Junit4的介绍 &#x1f30a;1.5 单元测试为什么要mock &#x1f3de;️…

《前端面试题》- React - 如何区分函数组件和类组件

问题 如何区分函数组件和类组件&#xff1f; 答案 可以使用instanceof 或者Component.prototype.isReactComponent。 示例 函数组件 export default function FunctionComonent() {if(FunctionComonent.prototype.isReactComponent){console.log(FunctionComonent是类组件…

prompt提示词:AI英语词典优化版Pro,让AI教你学英语,通过AI实现一个网易有道英语词典

目录 一、前言二、效果对比三、优化《AI英语词典》提示词四、其他获奖作品链接 一、前言 不可思议&#xff01;我的AI有道英语字典助手竟然与百度千帆AI应用创意挑战赛K12教育主题赛榜首作品差之毫厘 &#xff0c;真的是高手都是惺惺相惜的&#xff0c;哈哈&#xff0c;自恋一…