本想这种功能应该比较常见,谁知搜半天没找到。只能自己造轮!
效果图:
基于微信提供的picker-view实现的
js代码
// element/pickerex/index.js Component({ /** * 组件的属性列表 */ properties: { }, /** * 组件的初始数据 */ data: { value: [], tree: [], deep: 0, // 每列对应的数据 columnData: [], // 单位索引 idMap: undefined }, observers: { // 在 numberA 或者 numberB 被设置时,执行这个函数 'tree': function (tree) { // 建立id索引 let map = this.getIndexMap(tree) let deep = this.getMaxDepth(tree) // 排序 let value = [], data = [] for (let i = 0; i <= deep; ++i) value.push(0) // 默认值 this.getTreeData(tree, data) this.setData({ value: value, deep: deep, columnData: data, idMap: map }) } }, /** * 组件的方法列表 */ methods: { getIndexMap: function (tree) { let map = new Map() for (let e of tree) getDepth(e) function getDepth(e) { map.set(String(e.id), e) if (e && e.hasOwnProperty('children')) { for (let c of e.children) getDepth(c) } } return map }, getTreeData: function (treeData, data) { let deep = 0 data[deep] = treeData for (let e of treeData) { getDepth(e, deep + 1) break } function getDepth(e, deep) { if (e.hasOwnProperty('children') && e.children.length) { data[deep] = e.children for (let c of e.children) { getDepth(c, deep + 1) break } } } }, getMaxDepth: function (treeData, ans = {}) { for (let item of treeData) getDepth(item) function getDepth(e) { if (e.hasOwnProperty('children') && e.children.length) { ans[String(e.id)] = 0 for (let c of e.children) { ans[String(e.id)] = Math.max(ans[String(e.id)], getDepth(c) + 1) } return ans[String(e.id)] } else { ans[String(e.id)] = 0 return 0 } } let arr = Object.values(ans) return Math.max(...arr) }, getDataByIndex: function (index, data) { let tree = this.data.tree let deep = 0 data[deep] = tree getDepth(tree[index[deep]], deep + 1) function getDepth(e, deep) { if (e && e.hasOwnProperty('children') && e.children.length) { data[deep] = e.children getDepth(e.children[index[deep]], deep + 1) } } }, // getValueByIndex: function (index) { // let tmp = this.data.tree[index[0]] // for (let i = 1; i <= this.data.value.length; ++i) { // if (tmp && tmp.hasOwnProperty('children') && tmp.children.length > 0) { // tmp = tmp.children[index[i]] // if (!tmp) break // } // } // return tmp // }, bindChange: function (e) { let v = e.detail.value let val = this.data.value for (let i = 0; i < val.length; ++i) val[i] = 0 for (let i = 0; i < v.length; ++i) val[i] = v[i] let data = [] this.getDataByIndex(val, data) this.setData({ value: val, columnData: data }) }, bindTap: function (e) { // let dataset = e.currentTarget.dataset // 只是一个克隆对象,并不是本体,所以修改item的属性是不会改变tree中的节点 let tmp = e.currentTarget.dataset.item // console.log(dataset.column, dataset.item) // 此方法虽可找到对应位置值,不好找任意节点,只能找最后一个节点,可以根据点击的deep判断 // let item = this.getValueByIndex(this.data.value) // 但这个值貌似好不传,在wxml文件,所以采用索引方法 let map = this.data.idMap let item = map.get(String(tmp.id)) if (!item) return item.checked = !item.checked setChecked(item, item.checked) // 设置子节点选中 function setChecked(e, checked) { e.checked = checked if (e && e.hasOwnProperty('children')) { for (let c of e.children) setChecked(c, checked) } } // 设置父节点选中 if (item.checked) { item = map.get(String(item.pid)) while (item) { let full = true for (let e of item.children) { if (!e.checked) { full = false break } } if (full) item.checked = true // 如果有0节点会死循环,所以判断根节点跳出 if (item.pid === 0 || !full) break item = map.get(String(item.pid)) } } else { // 父节点反选 item = map.get(String(item.pid)) while (item) { item.checked = false // 如果有0节点会死循环,所以判断根节点跳出 if (item.pid === 0) break item = map.get(String(item.pid)) } } this.setData({ columnData: this.data.columnData }) // let val = this.data.value // let data = this.data.columnData this.triggerEvent('pickerChanged', { list: this.getCheckedList() }) }, getCheckedList: function () { let list = [] let tree = this.data.tree for (let e of tree) getChecked(e) // 设置子节点选中 function getChecked(e) { if (e.checked) list.push(e) if (e && e.hasOwnProperty('children')) { for (let c of e.children) getChecked(c) } } return list } } })
wxml(如果这个wx:for使用的item是本体就可以省掉建索引的过程,vue好像是本身,小程序是克隆体,修改dataset.item并不会修改数据源)
<!--element/pickerex/index.wxml--> <wxs module="wx"> var text = function (item) { // return item.name // 这里可以做一些输出字符串处理,如截断…… return item.name } module.exports = { text: text } </wxs> <picker-view indicator-style="height:50px;" style="width:100%;height:200px;color:gray;" value="{{value}}" bindchange="bindChange"> <picker-view-column wx:for="{{columnData}}" wx:key="index"> <view class="item" wx:for="{{item}}" wx:key="index" wx:for-item="child"> <text class="{{child.checked?'checked':''}}" bindtap="bindTap" data-item="{{child}}">{{wx.text(child)}}</text> </view> </picker-view-column> </picker-view>
wxss
.item { line-height: 50px; text-align: center; } .checked { border-bottom: 2px #3296FA solid; }
简短测试数据格式
[ { "name":"haha", "id":111223, "pid":3, "children":[ { "name":"还有?", "id":332211, "pid":111223 }, { "name":"真有", "id":332212, "pid":111223 } ] } ]
使用:
<pickerex id="area" bind:pickerChanged="pickerChanged"></pickerex>
记得json文件添加配置
"pickerex": "../../element/pickerex/index"
test...
收藏的用户(0) X
正在加载信息~
推荐阅读
站点信息
- 文章2305
- 用户1336
- 访客11455538
每日一句
Talent without working hard is nothing.
没有努力,天份不代表什么。
没有努力,天份不代表什么。
MySQL 数据库优化
This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its de
免ROOT实现模拟点击任意位置
Mobaxterm终端神器
CreateProcessW要注意的细节问题
Autonomous NAT Traversal
【教程】win10 彻底卸载edge浏览器
eclipse工程基于Xposed的一个简单Hook
排名前5的开源在线机器学习
Mac OS最简单及(Karabiner)快捷键设置
发一款C++编写的麻将
VMware NAT端口映射外网访问虚拟机linux
独家发布最新可用My-AutoPost——wordpress 采集器
新会员