您现在的位置是:网站首页> 编程资料编程资料
微信小程序实现多层级复选框菜单_javascript技巧_
2023-05-24
448人已围观
简介 微信小程序实现多层级复选框菜单_javascript技巧_
本文实例为大家分享了微信小程序自定义多层级复选框菜单的具体代码,供大家参考,具体内容如下
一、背景
因客户需要,有一个功能是需要注册用户时选择多个【单元 - 楼层 - 设备】的绑定,谷歌了一通,没有找到想要的,无奈之举只能手写一个…
二 、效果展示

三、功能点
1、初始化时,默认展开选中的菜单
2、点击每一层父级菜单,会自动折叠其子菜单
3、选中子级节点会默认选中父级节点
4、子级节点都没选中默认取消选中父级节点
5、选中父级节点默认选中其所有子级节点
四、代码实现

这里没写组件,如果需要可以改为组件。
可能会有一个疑问为哈是 treeMenu2 不是 treeMenu1
因为 treeMenu1 写的low,treeMenu2 升级了js代码。
1、treeMenu2.js
js里面的各种事件均为递归操作,可根据加载的数据动态进行操作。
// pages/biz/treeMenu/treeMenu.js Page({ /** * 页面的初始数据 */ data: { menuTreeImgLeft: "../../../icon/f_left.png", menuTreeImgBottom: "../../../icon/f_bottom.png", menuTree: [{ "checked": false, "children": [{ "checked": false, "children": [{ "id": "1-1-1", "checked": true, "field": "1", "title": "设备1", }, { "id": "1-1-2", "checked": false, "field": "2", "title": "设备2" }], "id": "1-1", "field": "1-floor", "title": "1楼", "isHidden": true, "bindAll": false, }, { "checked": false, "children": [{ "checked": false, "field": "3", "title": "设备3" }], "id": "1-2", "field": "2-floor", "title": "2楼", "isHidden": true, }, { "checked": false, "children": [{ "id": "1-3-4", "checked": true, "field": "4", "title": "设备4" }], "id": "1-3", "field": "3-floor", "title": "3楼", "isHidden": true, }], "id": "1", "isHidden": true, "bindAll": false, "field": "1-unit", "title": "1单元" }, { "checked": false, "children": [{ "checked": false, "children": [{ "id": "2-1-1", "checked": false, "field": "5", "title": "设备5" }], "id": "2-1", "field": "1-floor", "title": "1楼", "isHidden": true, }, { "checked": false, "children": [{ "id": "2-2-1", "checked": false, "field": "6", "title": "设备6" }], "id": "2-2", "field": "2-floor", "title": "2楼", "isHidden": true, }], "bindAll": false, "isHidden": true, "field": "2-unit", "title": "2单元", "id": "2", }], deepList: [], deepListOne: [] }, /** * 生命周期函数--监听页面显示 */ onShow: function () { this.checkForChecked() }, /** * 默认选中是否展开 */ checkForChecked() { var data = this.data.menuTree // 获取所有被选中的节点 var checkedNodes = this.getDeep(data) // 获取所有选中节点的父节点 checkedNodes.forEach(element => { var tmp = this.getParentsById(data, element.id) if (tmp != undefined && tmp.length > 0) { // 最后一级选中,默认展开和选中父级菜单 tmp.forEach(element => { element.isHidden = false element.checked = true }) } }) this.setData({ menuTree: data }) }, // 递归 - 根据id获取所有父节点 getParentsById(list, id) { for (let i in list) { if (list[i].id == id) { return [list[i]] } if (list[i].children) { let node = this.getParentsById(list[i].children, id); if (node !== undefined) { return node.concat(list[i]) } } } }, // 递归 - 根据id获取当前节点对象 getNodeById(data, id, newNodes = []) { data.forEach(element => { // 匹配到节点 if (element.id === id) { newNodes.push(element) } if (element.children) { this.getNodeById(element.children, id, newNodes) } }) return newNodes; }, // 递归 - 根据id获取所有子节点,(其实就是先获取当前id的节点对象,然后取当前对象,注意这里返回的是数组) getChildrenById(data, id, newNodes = []) { var list = data.children if (list != undefined) { list.forEach(element => { newNodes.push(element) if (element.children) { this.getChildrenById(element, id, newNodes) } }) } return newNodes; }, // 递归 - 获取所有选中节点 getDeep(data, newCheckedNodes = []) { data.forEach(element => { if (element.checked) { newCheckedNodes.push(element) } if (element.children) { this.getDeep(element.children, newCheckedNodes) } }) return newCheckedNodes }, // 递归 - 根据节点id获取兄弟所有节点 getBrotherNodesById(list, id) { // 非顶级节点:获取节点父节点对象里的children var parentNodes = this.getParentsById(list, id) if (parentNodes && parentNodes.length >= 2) { return parentNodes[1].children } // 顶级节点:第一级是自己,从原始数组中遍历第一层即可 return list }, // 根据当前节点id,获取及所有的父级兄弟节点的所有父节点 getParentBrotherAllNodesById(list, id) { var result = [] // 1、获取当前节点id父节点的父节点 var parentNodes = this.getParentsById(list, id) // 小于3表示当前父节点是顶级节点 if (parentNodes.length < 3) { return parentNodes[parentNodes.length - 1] } var testNode = parentNodes[2]; // 2、获取父节点的父节点所有兄弟节点 var children = testNode.children children.forEach(element => { var parentNodesById = this.getParentsById(list, element.id) if (parentNodesById.length >= 2) { // js 数组中添加多个元素 简单的方法 push(...[]) result.push(...(parentNodesById.slice(0, parentNodesById.length - 1))) } }); return result; }, /** * 点击事件 - 左侧绑定复选框事件 */ checkboxChangeBindAll(e) { var index = e.currentTarget.dataset.index; var index2 = e.currentTarget.dataset.index2; var list = this.data.menuTree if (index2 == undefined) { list[index].bindAll = !list[index].bindAll } if (index2 != undefined) { list[index].children[index2].bindAll = !list[index].children[index2].bindAll } console.log(this.data.menuTree); }, checkboxChange(e) { // console.log(e); console.log('checkbox发生change事件,携带value值为:', e.detail.value) const values = e.detail.value }, /** * 点击事件 - 右侧复选框事件 */ checkboxChangeAll(e) { var id = e.currentTarget.dataset.id; var data = this.data.menuTree var node = this.getNodeById(data, id) var childrenNodes = this.getChildrenById(node[0], id) // 1、子节点点选中状态-跟随父节点移动 node[0].checked = !node[0].checked // 节点下面的所有子节点跟随父节点的选中状态 childrenNodes.forEach(element => { element.checked = node[0].checked }) // 2、父节点选中状态,子节点都没选中,父节点默认不选中,子节点有一个选中,父节点也选中 // 获取同级兄弟节点 var bortherNodes = this.getBrotherNodesById(data, id) // 3、同级都选中 var allChecked = false bortherNodes.forEach(element => { if (element.checked) { allChecked = true } }) // 获取节点id所有父节点 var parentNodes = this.getParentsById(data, id) if (parentNodes.length > 1) { if (allChecked) { // 下标index=0的节点是其本身,这里跳过 for (let index = 1; index < parentNodes.length; index++) { const element = parentNodes[index]; element.checked = true } }else{ parentNodes[1].checked =false } } // 4、同级都未选中 if (!allChecked) { var allNoChecked = false // 根据当前节点id,获取除去顶级节点的所有的父级兄弟节点的所有父节点 var parentBother = this.getParentBrotherAllNodesById(data, id) console.log(parentBother); if (parentBother.length > 1) { parentBother.forEach(element => { if (element.checked) { allNoChecked = true } }); } console.log(allNoChecked); // console.log(parentBother); if(!allNoChecked){ parentNodes.forEach(element => { element.checked=false }); } }
相关内容
- 使用 React Hooks 重构类组件的示例详解_React_
- 微信小程序实现多选框全选操作_javascript技巧_
- vuex安装失败解决的方法实例_vue.js_
- Vue3如何通过ESLint校验代码是否符合规范详解_vue.js_
- 专业级Vue 多级菜单设计_vue.js_
- Shopee在React Native 架构方面的探索及发展历程_React_
- 手写Vue内置组件component的实现示例_vue.js_
- Vscode关闭Eslint语法检查的多种方式(保证有效)_vue.js_
- Vue项目中打包优化的四种方法详解_vue.js_
- 前端进阶JS数组高级用法大全教程示例_javascript技巧_
点击排行
本栏推荐
