项目原因,需要把一个扁平/线性数组转换成树形数组(符合 el-tree 数据要求)
const resData = [
{
id: '1', label: '动物', parentId: '', icon: '' },
{
id: '2', label: '狗', parentId: '1', icon: 'icon-chongwutubiao13' },
{
id: '3', label: '哈士奇', parentId: '2', icon: 'icon-hashiqi' },
{
id: '4', label: '柯基', parentId: '2', icon: 'icon-keji-' },
{
id: '6', label: '猫', parentId: '1', icon: 'icon-chongwutubiao04' },
{
id: '7', label: '植物', parentId: '', icon: '' },
{
id: '8', label: '微生物', parentId: '', icon: '' },
]
function transformData(data) {
// 深拷贝一份(以防连续调用出错)
const cData = JSON.parse(JSON.stringify(data))
const map = {
}
const tData = []
// 注意:这里item的引用地址指向cData
cData.forEach(item => (map[item.id] = item))
cData.forEach(child => {
const mapItem = map[child.parentId]
if (mapItem) {
// 注意:这里mapItem引用地址指向也是指向cData
if (!mapItem.children) mapItem.children = []
mapItem.children.push(child)
} else {
// 顶级节点
tData.push(child)
}
})
return tData
}
实现效果:
<template>
<el-scrollbar wrap-class="scrollbar-wrapper" style="height: 100%">
<el-tree
ref="tree"
v-loading="treeDataLoading"
node-key="id"
:data="treeData"
:show-checkbox="showCheckBox"
:default-expand-all="defaultExpandAll"
style="height: 100%; padding-bottom: 20px"
>
<span slot-scope="{ node, data }" class="custom-tree-node">
{
{ node.label }}
<template v-if="data.icon">
<el-tooltip effect="dark" :content="data.label" placement="top-start">
<i :class="['iconfont', data.icon]">i>
el-tooltip>
template>
span>
el-tree>
el-scrollbar>
template>
<script>
export default {
props: {
// 节点是否可被选择(显示前面的复选框)
showCheckBox: {
type: Boolean,
default: false,
},
// 是否默认展开所有节点
defaultExpandAll: {
type: Boolean,
default: false,
},
},
data() {
return {
treeData: [],
treeDataLoading: false,
resData: [
{
id: '1', label: '动物', parentId: '', icon: '' },
{
id: '2', label: '狗', parentId: '1', icon: 'icon-chongwutubiao13' },
{
id: '3', label: '哈士奇', parentId: '2', icon: 'icon-hashiqi' },
{
id: '4', label: '柯基', parentId: '2', icon: 'icon-keji-' },
{
id: '6', label: '猫', parentId: '1', icon: 'icon-chongwutubiao04' },
{
id: '7', label: '植物', parentId: '', icon: '' },
{
id: '8', label: '微生物', parentId: '', icon: '' },
],
}
},
methods: {
init() {
this.treeDataLoading = true
// 发送数据请求(这里不发送请求以resData模拟)
new Promise(res => {
const tree = this.resData
this.treeData = this.transformData(tree)
res()
})
.catch(() => {
})
.finally(() => {
this.treeDataLoading = false
})
},
transformData(data, params = {
}) {
const cData = JSON.parse(JSON.stringify(data))
const map = {
}
const tData = []
const attr = {
id: 'id',
parentId: 'parentId',
}
const arg = Object.assign({
}, attr, params)
cData.forEach(item => (map[item[arg.id]] = item))
cData.forEach(child => {
const mapItem = map[child[arg.parentId]]
if (mapItem) {
if (!mapItem.children) mapItem.children = []
mapItem.children.push(child)
} else {
tData.push(child)
}
})
return tData
},
// 全选
checkAll() {
this.$refs.tree.setCheckedNodes(this.treeData)
},
// 取消全选
cancelAll() {
this.$refs.tree.setCheckedKeys([])
},
},
}
script>
<style lang="less" scoped>
.scrollbar-wrapper {
overflow-x: hidden !important;
}
.custom-tree-node {
font-size: 16px;
}
style>
<template>
<div>
<tree-select ref="tree" defaultExpandAll />
div>
template>
<script>
import TreeSelect from './components/TreeSelect'
export default {
components: {
TreeSelect,
},
mounted() {
this.$refs['tree'].init()
},
}
script>
js 实现无限层级树形数据结构(创新算法)