Element-plus el-tree , el-select 联动实现 懒加载节点的树形选择器
element
A Vue.js 2.0 UI Toolkit for Web
项目地址:https://gitcode.com/gh_mirrors/eleme/element
免费下载资源
·
一:简介
选择器点击显示带有复选框的下拉选择器,并且支持带有父子关系的多选功能,Element-plus虽然存在el-tree-select 这一树形选择器,但是当下拉框节点是懒加载状态时且存在字父级关系(当选中父级时懒加载之后的子集在展开之后同样会被自动选中)时,如果要选择某一选框,则只能在树形结构懒加载完全展开之后的叶子节点才能被选中,否则是无法被选中的,此时就违背懒加载的初衷。
而使用el-tree, el-select 则可以实现在存在严格的父子关系的状态下,在整个树形结构没有完全加载之前,可以选中当前加载的任意节点
二:Dom元素结构
<el-select
v-model="dirSelect"
placeholder="请选择"
:collapse-tags="true"
@remove-tag="removeDirTag"
:collapse-tags-tooltip="true" multiple>
<el-option
style="
height: 100%;
max-height: 200px;
overflow-y: auto;
padding: 0;
background-color: #ffffff;">
<el-tree
v-model="treeOption"
ref="treeSelectRef"
node-key="value"
:load="loadNode"
:props="props"
:render-after-expand="true"
:show-checkbox="true"
lazy
@check-change="handleCheckChange">
</el-tree>
</el-option>
</el-select>
三:数据回显业务
因为是懒加载树形节点,则需要根据返回值进行分批次回显数据,而返回的数据也应该是分组数据,这样才能在节点加载之后准确回显,主要使用:load 、setChecked、
//变量
const state = reactive<any>({
checkDirEchoInfo: {}, //保存授权目录分层回显的所有信息
dirSelect:[] //用户select回显标签
})
//分层回显核心逻辑
const loadNode = (node:any, resolve:any) => {
if (node.isLeaf) return resolve([])
if(node.level === 0){
getDept().then((res)=>{
console.log('dept00000',res.data)
if(res && res.status as any === '200'){
if(!res.data){
resolve([])
}else{
resolve(
res.data.map((item:any)=>{
return {
label:item.deptName,
value:item.code,
type:'dept',
parentCode:'-',
}
})
)
}
}
})
}else if(node.level === 1){
let params = {
deptCode:node.data.value,
pageNum:1,
pageSize:20
}
projectList(params).then((res)=>{
console.log('dept1',res.data)
if(res && res.status as any === '200'){
console.log('projectList',res.data.records)
if(!res.data){
resolve([])
}else{
let temp = res.data.records.map((item: any) => {
return {
value: item.projectInfo.code,
label: item.projectInfo.projectName,
parentCode: item.projectInfo.departmentCode,
type: "project",
};
});
resolve(temp);
console.log("当前加载的第二层节点", temp);
//将第二层节点用排除法进行回显
if (temp.length > 0) {
let checked = false;
let allChecked = false;
temp.forEach((el: any) => {
console.log(el.parentCode);
if(state.checkDirEchoInfo.project.length>0){
state.checkDirEchoInfo.project.forEach((item: any) => {
console.log("code", el.value === item.contentsCode);
if (el.value === item.contentsCode) {
//当前子节点被选中
checked = true;
//是否存在子节点被选中
allChecked = true;
}
});
}
//设置当前节点是否被勾选,若勾选则并递归选择子节点
treeSelectRef.value.setChecked(el.value, checked, true);
//更新标识
checked = false;
});
//如果当第二层没有一个被选中,且其父元素是被选中的,则设置当前层全选
if (!allChecked) {
state.checkDirEchoInfo.dept.forEach((item: any) => {
if (temp[0].parentCode === item.contentsCode) {
//此时该层元素均为选中状态,并且默认递归选中子节点中的数据
treeSelectRef.value.setChecked(temp[0].parentCode,true,true);
}
});
allChecked = false;
}
}
}
}
})
}else if(node.level === 2){
getProjectDirectory(false,node.data.value).then((res)=>{
if(res && res.status as any === '200'){
if (!res.data) {
resolve([]);
} else {
let temp = res.data.map((item: any) => {
return {
value: item.code,
label: item.directoryName,
parentCode: item.projectCode,
children: item.sonDirectoryList,
isLeaf: item.sonDirectoryList ? false : true,
type: !item.isDirectory ? "file" : "Directory",
};
});
resolve(temp);
if (temp.length > 0) {
let checked = false;
let allChecked = false;
//获取当前层加载前的所有被选中的节点
let checkedNodes = treeSelectRef.value.getCheckedNodes();
temp.forEach((el: any) => {
state.checkDirEchoInfo.dirFile.forEach((item: any) => {
if (el.value === item.contentsCode) {
//当前子节点是否被选中
checked = true;
//当前层是否存在节点被选中
allChecked = true;
}
});
//设置当前元素的选中状态,若选中则递归勾选其子节点
treeSelectRef.value.setChecked(el.value, checked, false);
checked = false;
});
//如果当前一层没有一个被选中,且其父元素是被选中的,则设置当前层全选
if (!allChecked) {
checkedNodes.forEach((item: any) => {
if (temp[0].parentCode === item.value) {
//若其父元素被选中,则默认选勾选当前层所有元素,并递归勾选其子元素
treeSelectRef.value.setChecked(temp[0].parentCode,!allChecked,true);
}
});
allChecked = false;
}
}
}
}
})
}else if(node.level >2){
let temp = getChild(node.data.children);
resolve(temp)
if (temp!==undefined && temp.length > 0) {
let checked = false;
let allChecked = false;
//获取该层加载前所有被选中的元素
let checkedNodes = treeSelectRef.value.getCheckedNodes();
temp.forEach((el: any) => {
state.checkDirEchoInfo.dirFile.forEach((item: any) => {
if (el.value === item.contentsCode) {
//当前加载的元素是否被选中
checked = true;
//当前层是否存在元素被选中
allChecked = true;
}
});
treeSelectRef.value.setChecked(el.value, checked, true);
checked = false;
});
//如果当前一层没有一个被选中,且其父元素是被选中的,则设置当前层全选
if (!allChecked) {
checkedNodes.forEach((item1: any) => {
treeSelectRef.value.setChecked(
temp[0].parentCode,
!allChecked,
true
);
});
allChecked = false;
}
}
}
}
四:注意事项,
1,设置node-key为节点设置Key值
2,数据回显不推荐设置禁用状态回显,因为禁用状态下setChedked方法为某一元素设置选中状态时不能自动勾选其子元素,此时如果逻辑补充完整也是能实现功能的,但是经过测试el-tree树形结构只能递归绑定五层数据,第六层数据就会脱离第五层的childrenList属性,通过api无法被通过代码设置选中,则和禁用状态同时使用时就不能支持五层以上的数据结构回显了。
GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:3 个月前 )
c345bb45
7 个月前
a07f3a59
* Update transition.md
* Update table.md
* Update transition.md
* Update table.md
* Update transition.md
* Update table.md
* Update table.md
* Update transition.md
* Update popover.md 7 个月前
更多推荐
已为社区贡献6条内容
所有评论(0)