情形:树形下拉列表有大量深度嵌套的选项时,为保证前端性能,需要延迟加载选项。但是有时筛选条件需要记忆,再次进入页面时要自动回显已勾选的选项。

实现功能:

  • 异步搜索
  • 延迟加载
  • 记忆被勾选子节点的各级父节点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
在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐