vue3 encapsulates the form component (2) 02 The use of el-tree-select component - lazy loading, data echo & the combination of el-tree and el-select
Requirement: Display in a tree structure drop-down when selecting an organization.
el-tree-select
Components are a combination of el-tree
and el-select
, their original properties have not been changed, so the specific properties and methods still refer to el-tree
andel-select
Install
npm install el-tree-select --save-dev
git address
https://github.com/ayiaq1/el-tree-select
Reference document address:
- https://element-plus.gitee.io/zh-CN/component/tree-select.html
- https://element-plus.gitee.io/zh-CN/component/tree.html
npm address—— el-tree-select - npm (npmjs.com)
github address—— GitHub - ayiaq1/el-tree-select: Extended drop-down tree based on element-ui2.x
Online API - ElTreeSelect - el-tree-select (ayiaq1.github.io)
Online testing - rendering - passing parameters through props ⋅ Storybook (ayiaq1.github.io)
npm example
<template>
<div id="app">
<el-tree-select :styles="styles" v-model="values" :selectParams="selectParams" :treeParams="treeParams" :treeRenderFun="_renderFun" @searchFun="_searchFun" @node-click="_nodeClickFun" ref="treeSelect"/>
<el-select multiple v-model="test" placeholder="请选择" @change="_selectChange">
<el-option v-for="item in treeParams.data" :key="item.testId" :label="item.name" :value="item.testId"></el-option>
</el-select>
</div>
</template>
<style>
#app {
display: flex;
justify-content: space-between;
width: 600px;
}
</style>
<script>
export default {
name: 'App',
data() {
return {
styles: {
width: '300px'
},
test: '',
values: ['11111'],
selectParams: {
multiple: true,
clearable: true,
placeholder: '请输入内容'
},
treeParams: {
clickParent: false,
filterable: true,
'check-strictly': true,
'default-expand-all': true,
'expand-on-click-node': false,
data: [],
props: {
children: 'child',
label: 'name',
disabled: 'disabled',
value: 'testId'
}
}
};
},
mounted() {
let data = [
{
testId: '1',
name: '节点1',
disabled: true,
child: [
{
testId: '11111',
name: '子节点'
}
]
},
{
testId: '2',
name: '节点2',
child: [
{
testId: '222222',
disabled: true,
name: '子节点'
}
]
},
{
testId: '3',
name: '节点3'
},
{
testId: '4',
name: '节点4'
},
{
testId: '5',
name: '节点5'
},
{
testId: '6',
name: '节点6'
}
];
this.treeParams.data = data;
this.$refs.treeSelect.treeDataUpdateFun(data);
},
methods: {
// 下拉框修改
_selectChange(val) {
console.log(val, '<-select change');
},
// 树点击
_nodeClickFun(data, node, vm) {
console.log('this _nodeClickFun', this.values, data, node);
},
// 树过滤
_searchFun(value) {
console.log(value, '<--_searchFun');
// 自行判断 是走后台查询,还是前端过滤
// this.$refs.treeSelect.$refs.tree.filter(value);
this.$refs.treeSelect.filterFun(value);
// 后台查询
// this.$refs.treeSelect.treeDataUpdateFun(treeData);
},
// 自定义render
_renderFun(h, { node, data, store }) {
return (
<span class='custom-tree-node'>
<span>{node.label}</span>
</span>
);
}
},
components: { }
};
</script>
use
structure
<el-tree-select
v-model="form.deptId"
lazy
ref="treeRef"
:load="loadNode"
:props="{ value: 'deptId', label: 'deptName'}"
value-key="deptId"
node-key="deptId"
placeholder="请选择"
show-checkbox
check-strictly
highlight-current
:default-expanded-keys="defaultExpandedNodes"
/>
Property description
parameter | Definition |
---|---|
v-model | id value. As long as the id value can be matched in the tree, its label value can be successfully echoed. |
lazy | Enable lazy loading |
load | How to load subtree data |
value-key | The key name that uniquely identifies the value. Simply put, it is the primary key, which is modified according to the fields returned by your own backend. |
node-key | Each tree node uses an attribute as a unique identifier. Simply understood as the primary key of the tree node, the same as value-key |
props | Configuration options. Generally configure the attribute values of value and label |
show-checkbox | Enable checkbox |
check-strictly | You can choose any level |
highlight-current | Check highlight |
default-expanded-keys | The key array of the node is expanded by default (used for data echo during lazy loading, this attribute is very critical) |
methods
/** 懒加载获取树形结构*/
function loadNode(node, resolve) {
// node其实是需要展开树节点,但是第一次的node是个无用的数据,可以认为这个node是element给我们创建的,判断的话,就是level等于0
if (node && node.level == 0) {
getDeptData(0, resolve);
} else {
getDeptData(node, resolve);
}
}
// 从后端获取数据列表
function getDeptData(node, resolve){
//构造参数
let params = {
};
params.pageSize = 100;
if(node == 0){
//根节点
params.deptId = '1';
}else if(node.data.deptId){
//中间节点
params.parentId = node.data.deptId;
}else{
return resolve([]);
}
// listDept是像后端访问组织结构数据的接口,根据实际场景修改
listDept(params).then(response => {
let data = response.data;
return resolve(data);
})
}
echo
Due to the use of lazy loading, unlike loading all the data at once, there is currently only the ID, and the tree structure has not yet been rendered, resulting in no label echo. So we need to construct the tree nodes we want when the component is just rendered.
The attribute is used default-expanded-keys
to represent the key array of the default expanded node. el-tree-select will automatically call the loadNode method according to this keys array, obtain data and render tree nodes.
default-expanded-keys
There are two ways of thinking about the value:
- When adding/modifying, obtain the key path from the top-level root node to the currently selected node, for example: ['01','0101','010101'], and save it to the data table.
- Add such a field to the dept data table, the key path from the root node to the current node
Finally, while getting the content of the current data form, just assign the keys path of the node to be expanded default-expanded-keys
, and it will expand to the current node by default and successfully echo the label.