elementUI树状图----费好大的劲

我写的树状图因为数据量过大,所以写的是默认打开两级,子级的当点击父级才会加载,这样不会造成页面卡顿问题。

一个月前写的了,直接贴代码了。

 

 同样,结合面向百度求知的部分。

    /**
     * 下拉选择树形组件,下拉框展示树形结构,提供选择某节点功能,方便其他模块调用
     * 调用示例:
     * <tree-select :height="400" // 下拉框中树形高度
     *              :width="200" // 下拉框中树形宽度
     *              :data="data" // 树结构的数据
     *              :defaultProps="defaultProps" // 树结构的props
     *              multiple   // 多选
     *              :rootNodeChick="true" // 是否可以选择根节点。默认 false ture 为可选。false 为不可选
     *              checkStrictly // 多选时,严格遵循父子不互相关联
     *              :nodeKey="nodeKey"   // 绑定nodeKey,默认绑定'id'
     *              :checkedKeys="defaultCheckedKeys"  // 传递默认选中的节点key组成的数组
     *              :render-after-expand="false"   // 是否在第一次展开某个树节点后才渲染其子节点 默认true false直接渲染
     *              :default-expanded-keys="idArr"  // 默认展开的节点的 key 的数组
     *              @popoverHide="popoverHide"> // 事件有两个参数:第一个是所有选中的节点ID,第二个是所有选中的节点数据
     *</tree-select>
     *
     * import TreeSelect from "@/utils/components/tree-select.vue";
     * components: { TreeSelect },
     *
     *数据格式
     *let obj = {
                "id": "10",
                "label": "琼瑶作品集",
                "children": [],
                  };
     * 清空树的选中状态。只需要将clear 从 0 累加就可以。这里是监听的数据改变状态。不为 0 则清空数据。Number类型
     */
 <div class="content-body" style="padding:0">
    <div style="width:820px;" class="pull-left">
      <div style="width:284px; display: inline-block;margin-left: -5px">
        <div class="search-box ml10 mt20" style="max-width:275px">
          <input v-model.trim="filterText" type="text" placeholder="搜索" class="form-                    input" style="width: 260px"/><i @click="search" style="top: 3px;"></i>
        </div> 
        <el-tree 
          class="common-tree mt20 ml10"
          :style="style"
          clearable
          ref="tree"
          :data="data"
          :props="defaultProps"
          :show-checkbox="multiple"
          :node-key="nodeKey"
          :check-strictly="checkStrictly"
          :default-expand-all='false'
          :default-expanded-keys="idArr"
          :render-after-expand="true"  
          :expand-on-click-node="false"
          :default-checked-keys="defaultCheckedKeys"
          :highlight-current="true"
          :filter-node-method="filterNode"
          @node-click="handleNodeClick"
          @check-change="handleCheckChange"></el-tree>
          <!-- @check="changeCheck" -->
      </div>
    </div>
    <div class="right-box pull-right" style="height: 600px; width:250px">
      <div style="height: 46px;line-height:46px;">
        <span>已选择:</span>
        <span class="hand pull-right" style="color: #3171b9" @click="clearAll">清除所有</span>
      </div>
      <ul class="dept-box border" style="height: 400px; width:250px; padding-left: 8px">
        <li class="deptItem pull-left" style="min-width:120px" v-for="(item, index) in options" :key="index">
        <img src="@/../static/images/userSelector/ico_dept.png" alt="">
        {{item.label}}
        <img src="@/assets/img/ico8.png" alt="" class="delimg hand" @click="del(item)">
        </li>
      </ul>
    </div>
  </div>

script部分

export default {
    name: "tree-select",
    // props: ["clear"],
    props: {
      // 树结构数据
      // data: {
      //   type: Array,
      //   default () {
      //     return [];
      //   }
      // },
      // 是否可选根节点
      rootNodeChick: Boolean,
      // 是否清空数据
      clear: Number,
      defaultProps: {
        type: Object,
        default () {
          return {};
        }
      },
      // 配置是否可多选
      multiple: {
        type: Boolean,
        default () {
          return false;
        }
      },
      nodeKey: {
        type: String,
        default () {
          return "id";
        }
      },
      // 显示复选框情况下,是否严格遵循父子不互相关联
      checkStrictly: {
        type: Boolean,
        default () {
          return true;
        }
      },
      // 默认选中的节点key数组
      checkedKeys: {
        type: Array,
        default () {
          return [];
        }
      },
      width: {
        type: Number,
        default () {
          return 275;
        }
      },
      height: {
        type: Number,
        default () {
          return 400;
        }
      },
    },
    data () {
      return {
        defaultCheckedKeys: [],
        isShowSelect: true, // 是否显示树状选择器
        options: [],
        selectedData: [], // 选中的节点
        style: "width:" + this.width + "px;" + "height:" + this.height + "px;",
        selectStyle: "width:" + (this.width + 24) + "px;",
        checkedIds: [],
        checkedData: [],
        filterText: '',
        tabs: [
          {
            title: '选择部门',
            active: true
          },
        ],
        // checkStrictly: true,
        idArr: [],
        data: []
      };
    },
    mounted () {
      this.getTree()
      if (this.checkedKeys.length > 0) {
        if (this.multiple) {
          this.defaultCheckedKeys = this.checkedKeys;
          this.selectedData = this.checkedKeys.map(item => {
            var node = this.$refs.tree.getNode(item);
            return node.label;
          });
        } else {
          var item = this.checkedKeys[0];
          this.$refs.tree.setCurrentKey(item);
          var node = this.$refs.tree.getNode(item);
          this.selectedData = node.label;
        }
      }
    },
    methods: {
      // 父选 子全选
      // 父不选 子不操作
      changeCheck(currentObj, statusObj) {
        let selected = statusObj.checkedKeys.indexOf(currentObj.id)
        if(selected !== -1) {
          this.uniteChildSame(currentObj, true)
        }else {
          if (!currentObj.children) {
            this.uniteChildSame(currentObj, false)
          }
        }
      },
      // 统一处理子节点为相同的勾选状态
      uniteChildSame (treeList, isSelected) {
        this.$refs.tree.setChecked(treeList.id, isSelected)
        if(treeList.children) {
          for (let i = 0; i < treeList.children.length; i++) {
            this.uniteChildSame(treeList.children[i], isSelected)
          }
        }
      },
      // 统一处理父节点为选中
      selectedParent (currentObj) {
        let currentNode = this.$refs.tree.getNode(currentObj)
        if (currentNode.parent.key !== undefined) {
          this.$refs.tree.setChecked(currentNode.parent, true)
          this.selectedParent(currentNode.parent)
        }
      },
      del(i) {
        this.options = this.options.filter(item => item.value !== i.value)
        this.$refs.tree.setChecked(i.value,false,true);
      },
      search() {
        this.$refs.tree.filter(this.filterText)
      },
      filterNode(value, data) {
        if (!value) return true;
        return data.name.indexOf(value) !== -1;
      },    
      loadCheckedKeys () {
        if (this.checkedKeys.length > 0) {
          if (this.multiple) {
            this.defaultCheckedKeys = this.checkedKeys;
            this.selectedData = this.checkedKeys.map(item => {
              var node = this.$refs.tree.getNode(item);
              return node.label;
            });
          } else {
            var item = this.checkedKeys[0];
            this.$refs.tree.setCurrentKey(item);
            var node = this.$refs.tree.getNode(item);
            this.selectedData = node.label;
          }
        }
      },
      popoverHide () {
        if (this.multiple) {
          this.checkedIds = this.$refs.tree.getCheckedKeys(); // 所有被选中的节点的 key 所组成的数组数据
          this.checkedData = this.$refs.tree.getCheckedNodes(); // 所有被选中的节点所组成的数组数据
        } else {
          this.checkedIds = this.$refs.tree.getCurrentKey();
          this.checkedData = this.$refs.tree.getCurrentNode();
        }
        this.$emit("popoverHide", this.checkedIds, this.checkedData);
      },
      // 节点被点击时的回调,返回被点击的节点数据
      handleNodeClick (data, node) {
        if (!this.multiple) {
          let tmpMap = {};
          tmpMap.value = node.key;
          tmpMap.label = node.label;
          this.options = [];
          this.options.push(tmpMap);
          this.selectedData = node.label;
        }
      },
      // 节点选中状态发生变化时的回调
      handleCheckChange () {
        var checkedKeys = this.$refs.tree.getCheckedKeys(); // 所有被选中的节点的 key 所组成的数组数据
        this.options = [];
        if (!this.rootNodeChick) {
          checkedKeys.forEach(item => {
            var node = this.$refs.tree.getNode(item); // 所有被选中的节点对应的node
            let tmpMap = {};
            tmpMap.value = node.key;
            tmpMap.label = node.label;
            this.options.push(tmpMap);
          });
        }else {
          this.options = checkedKeys.map(item => {
            var node = this.$refs.tree.getNode(item); // 所有被选中的节点对应的node
            let tmpMap = {};
            tmpMap.value = node.key;
            tmpMap.label = node.label;
            return tmpMap;
          });
        }
        this.selectedData = this.options.map(item => {
          return item.label;
        });
      },
      clearAll() {
        this.options = []
        this.$nextTick(() => {
          this.$refs.tree.setCheckedKeys([]);
        });
      },
      setChecked(keys, leafOnly) {
        keys.forEach(item => {
          var node = this.$refs.tree.getNode(item); // 所有被选中的节点对应的node
          if(!node) return
          let tmpMap = {};
          tmpMap.value = node.key;
          tmpMap.label = node.label;
          this.options.push(tmpMap);
          for (let i = 0; i < this.options.length; i++) {
            for (let j = i + 1; j < this.options.length; j++) {
              if(this.options[i].value === this.options[j].value) {
                this.options.splice(j, 1)
                j = j - 1
              }
            }
          }
        });
        this.$nextTick(() => {
          this.$refs.tree.setCheckedKeys(keys, leafOnly);
        })
      },
      getTree() {
        getDeptList().then(res => {
          const map = {};
          const val = [];
          if(!res.data) return
          res.data.forEach((item) => {
            map[item.id] = item;
          });
          res.data.forEach((item) => {
            const parent = map[item.parentId];
            if (parent) {
              (parent.children || (parent.children = [])).push(item);
            } else {
              val.push(item);
            }
          });
          this.data = val; 
        })
      },      
    },
    watch: {
      clear: function (n, o) {
        //箭头函数  不然会发生this改变
        if (n != 0) {
          this.selectedData = [];
          this.$nextTick(() => {
            this.$refs.tree.setCheckedKeys([]);
          });
        }
      },
      selectedData: function (newData, oldData) {
        this.popoverHide();
        if (
          newData == undefined ||
          newData == null ||
          newData == [] ||
          newData.length == 0
        )
          this.$refs.tree.setCheckedKeys([]);
      },
      // filterText(value) {
      //   this.$refs.tree.filter(value)
      // },
      data: {
        // 显示两级数据
        handler() {
          this.data.forEach(item => {
            this.idArr.push(item.id)
          })
        },
        deep: true
      }
    }
  };

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值