起因
前端有个树形结构需要显示, 层级比较多, 达到7层, 还是需要自适应大小. 现有的组件要不层级不够, 例如像省市县这样的级联, 只有3层, 如果做成7层, 在移动端显示效果不好.
在网上发现yangjingyu/vs-tree
比较符合要求, 上面用面包屑显示层级, 下面只显示最后一层的列表. 不过在vue3上有些问题. 刚好最近接触了hooks
, 还了解了Headless UI
. 把逻辑和ui
进行分离, 以前看过(用积木理论设计一个灵活好用的Carousel走马灯组件), 也想过, 只是不知道这样一个统一的名称.
目前常见的组件通过slot
来定制化还是不够灵活.
灵活性:1
手写逻辑和ui > hooks + 手写ui > ui框架组件
当然灵活性越大, 工作量也越大.
实例
输入: data
是一个扁平的树, id为”_”的是根节点.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17{
"_": {
"id": "_",
"name": "_",
"children": ["1", "2"]
},
"1": {
"id": "1",
"name": "1",
"children": []
},
"2": {
"id": "2",
"name": "2",
"children": []
}
}
输出: 导出4个变量, breadcrumbNodes
,breadcrumbNodeClick
,是上面面包屑的节点列表, 和点击函数, currentNodes
, currentNodeClick
是下面的节点列表和点击函数.
1 | # useTree.js |
使用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32<script setup>
import useTree from './useTree'
const data2 = {}
const { breadcrumbNodes, currentNodes, breadcrumbNodeClick, currentNodeClick } = useTree(data2)
const listclick2 = (index) => {
const node = currentNodes.value[index]
console.log('listclick2', index, node.name)
currentNodeClick(index)
}
</script>
<template>
<div>
<div class="tree-box">
<div class="tree-breadcrumb">
<span v-for="(item, index) in breadcrumbNodes" :key="item.id" @click="breadcrumbNodeClick(index)">
<span class="tree-breadcrumb-start" v-if="index == 0">@</span>
<span class="tree-breadcrumb-link">{{ item.name }}</span>
<span class="tree-breadcrumb-separator" v-if="index != breadcrumbNodes.length - 1">/</span>
</span>
</div>
<ul class="tree-list">
<li v-for="(item, index) in currentNodes" :key="item.id" @click="listclick2(index)">
{{ item.name }}
</li>
</ul>
</div>
</div>
</template>