本想这种功能应该比较常见,谁知搜半天没找到。只能自己造轮!
效果图:
基于微信提供的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
正在加载信息~
推荐阅读
站点信息
- 文章2313
- 用户1336
- 访客11763919
每日一句
Trust your choices. Follow your heart to your destiny.
相信你的选择。追随你的心意走向你的命运。
相信你的选择。追随你的心意走向你的命运。
Android自定义蜂窝布局
ConstraintLayout布局初试之环形动画效果
新手安装黑苹果OS X 10.11教程
umeditor富文本编辑器插件扩展
【黑苹果安装】——如何在windows下操作EFI分区
java.nio.ByteBuffer缓冲区简介
adb logcat 命令行用法
请启用虚拟机平台 windows 功能并确保在 bios 中启用虚拟化
Windows+Linux平台Socket底层封装
Project Treble让Android更新速度更快
全局AfxMessageBox默认标题修改
亲测!虚拟机VirtualBox安装MAC OS 10.12图文教程
thinkpad t470p装黑苹果系统10.13.2
新会员