情形:树形下拉列表有大量深度嵌套的选项时,为保证前端性能,需要延迟加载选项。但是有时筛选条件需要记忆,再次进入页面时要自动回显已勾选的选项。
实现功能:
- 异步搜索
- 延迟加载
- 记忆被勾选子节点的各级父节点id,以便再次进页面时回显勾选项
<vue-tree-select
v-model="filterForm.columnId"
:async="true"
:default-expand-level="1"
:load-options="loadOptions"
:maxHeight="660"
:multiple="true"
:options="channelOptions"
:defaultOptions="true"
:value-consists-of="valueConsistsOf"
alwaysOpen
placeholder="搜索"
searchPromptText="输入关键词搜索"
noChildrenText="暂无数据"
noOptionsText="暂无可选项"
noResultsText="暂无匹配项"
loadingText="数据加载中"
clearAllText="清空所选项"
@select="onSelect"
@deselect="onDeselect"
>
由于勾选子节点时无法直接得知其多级父节点的id值,因此需要在@select、@deselect方法中额外存一下parentColumnId数组
import VueTreeselect, { LOAD_CHILDREN_OPTIONS, ASYNC_SEARCH } from "@riophae/vue-treeselect";
export default {
components: {
"vue-tree-select": VueTreeselect
},
data() {
return {
channelOptions: [
{
id: 123,
label: "顶级节点",
children: null,
has_child: true,
loading: false,
disableCheckbox: true
}
],
valueConsistsOf: "BRANCH_PRIORITY", // ALL" "BRANCH_PRIORITY" "LEAF_PRIORITY" "ALL_WITH_INDETERMINATE
filterForm: {
columnPathId: [],
parentColumnId: [],
columnId: []
},
allPath: [],
loadLevel1: false
};
},
watch: {
loadLevel1(loaded) {
if (loaded) {
// 插件设置第一层自动展示,loadLevel1:true代表第一层已加载完成
// 这时候再执行回显逻辑
this.backShowNode(this.channelOptions, this.allPath, 0);
}
}
},
methods: {
onSelect(node) {
if (node.has_child) {
this.filterForm.parentColumnId.push(node.id);
}
this.filterForm.columnPathId.push(String(node.parentId));
},
onDeselect(node) {
this.filterForm.columnPathId = this.filterForm.columnPathId.filter(
pathId => node.parentId !== pathId
);
},
// 离开时存储筛选条件
saveParams() {
let filterItems = this.filterForm;
// columnPathId 整合一下 谁是第一级谁是第二级
let allPathObj = {};
filterItems.columnPathId.forEach(str => {
str.split("##").forEach((id, i) => {
if (!allPathObj[i]) {
allPathObj[i] = [];
}
allPathObj[i].push(id);
});
});
// 去重
let allPath = Object.values(allPathObj).map(arr => [...new Set(arr)]);
let params = {
allPath,
filterItems,
};
sessionStorage.setItem("filter_params", JSON.stringify(params));
},
// 回到页面时 从sessionStorage获取筛选条件
getParams() {
let localSave = sessionStorage.getItem("filter_params");
if (localSave && localSave !== "") {
localSave = JSON.parse(localSave);
const { filterItems, allPath } = localSave;
this.allPath = allPath;
this.filterForm = { ...filterItems };
sessionStorage.setItem("filter_params", "");
}
},
async loadOptions({ action, parentNode, searchQuery, callback }) {
if (action === LOAD_CHILDREN_OPTIONS) {
if (parentNode.has_child) {
parentNode.children = await this.asyncLoadTreeData(parentNode);
this.loadLevel1 = true;
callback();
}
} else if (action === ASYNC_SEARCH) {
if (searchQuery) {
let searchChannelList = await this.handleSearchChannel(searchQuery);
callback(null, searchChannelList);
} else {
callback(null, this.channelOptions);
}
}
},
// 异步搜索
async handleSearchChannel(keyword) {
// 后端查询...
},
// 懒加载树
async asyncLoadTreeData(parentNode, callback) {
console.log(parentNode);
let res = await getlazyTreeData(parentNode.id); // ajax请求
if (res.status === 200) {
let arr = res.data.data.map(item => {
let { parentId, id } = parentNode;
// 插件不支持直接通过子节点node获取该节点上的全部父节点
// 自己记录在子节点node里面 用##分隔
parentId = parentId ? `${parentId}##${id}` : id;
let obj = {
...item,
parentId,
id: item.id,
label: item.name
};
if (item.has_child) {
obj.children = null;
}
return obj;
});
return arr;
} else {
this.$Message.error(res.data.message);
return [];
}
},
},
解释一下,node节点记录parentId为每一级父节点的组合,比如1##23