登录
    Technology changes quickly but people's minds change slowly.

vue Cascader 级联面板使用整理

开源分享 破玉 3168次浏览 0个评论

    最近有个功能需要用到级联相关的操作,再element上看到有相关组件,就直接拿来用了
https://element.eleme.cn/#/zh-CN/component/cascader

<el-cascader-panel :options="options"></el-cascader-panel>

    但是官方文档上给的方法和属性也不是很全面,只有简单的操作,像其他手动操作的方法以及展开,回显等操作均没有展示
    下面将该组件的一些用法总结一下:
首先我们需要阅读下源码:
https://github.com/ElemeFE/element/tree/dev/packages/cascader-panel/src
很多操作看源码就能很清楚的找到
首先我们使用该组件,并为其指定 ref,这样我们就能通过ref 调用组件的方法了

<el-cascader-panel ref="mycas2" :options="options2" :props="props" v-model="data2" @change="getData"></el-cascader-panel>

获取选中的节点,这个方法在文档上也有说明:
getCheckedNodes获取选中的节点数组 (leafOnly) 是否只是叶子节点,默认值为 false

this.$refs.mycas2.getCheckedNodes()// 包含选中的父节点
this.$refs.mycas2.getCheckedNodes(true)// 只有叶子节点

通过外部方法,选中或者取消选中节点,而不是直接点击节点选中,一般用于自定义需求以及回显。
首选我们得能取到目标节点,然后才能进行下一步操作,对于回显来说,你可以采用v-model 绑定的值回显,需要按照指定格式复制给model即可,我们不采用这种方式,我们直接找节点进行回显,我们有了值,需要根据该值查找节点,在源码里面我们可以找到这个方法

 getNodeByValue(val) {
      return this.store.getNodeByValue(val);
 },

那我们也可以直接调用了

this.$refs.singleCascader.getNodeByValue(value)

找到节点如何进行选中操作呢,我们需要看下节点的源码
https://github.com/ElemeFE/element/blob/dev/packages/cascader-panel/src/node.js
源码如下

 doCheck(checked) {
    if (this.checked !== checked) {
      if (this.config.checkStrictly) {
        this.checked = checked;
      } else {
        // bottom up to unify the calculation of the indeterminate state
        this.broadcast('check', checked);
        this.setCheckState(checked);
        this.emit('check');
      }
    }
  }

我们就可以直接进行调用

this.$refs.singleCascader.getNodeByValue(value).doCheck(true) // 选中
this.$refs.singleCascader.getNodeByValue(value).doCheck(false) // 取消选中

但是我们发现做了上面操作之后,发现并没有生效,没有选中
又读了一下源码,发现 doCheck 之后,多选需要执行下 calculateMultiCheckedValue 方法,可以在清空所有选中节点的代码中看到
源码如下:

clearCheckedNodes() {
      const { config, leafOnly } = this;
      const { multiple, emitPath } = config;
      if (multiple) {
        this.getCheckedNodes(leafOnly)
          .filter(node => !node.isDisabled)
          .forEach(node => node.doCheck(false));
        this.calculateMultiCheckedValue();
      } else {
        this.checkedValue = emitPath ? [] : null;
      }
    }

于是我们还需要如下操作:

  this.$refs.mycas2.calculateMultiCheckedValue() 

通过外部方法选中或者取消选中,思路与上面类似,需要找到该节点或者有该节点的值即可

然后就是自动展开功能,展开到某个层级,源码中看到有展开所有节点的方法

expandNodes(nodes) {
      nodes.forEach(node => this.handleExpand(node, true /* silent */));
  },

如果展开到某个节点我们可以直接

this.$refs.mycas2.handleExpand(node,true)

如果是初始加载就展开,可以如下设置,自己根据层级展开即可

 if(this.$refs.mycas2){
                  this.$nextTick(()=>{
                    let caspanel=this.$refs.mycas2
                    let node= caspanel.menus[0]
                    caspanel.handleExpand(node,true)
                    caspanel.handleExpand(node[0],true)
         })
    }

清除所有选中节点,官方文档也已经写清楚了

this.$refs.mycas2.clearCheckedNodes()

示例代码如下:

<template>
   <div>
     <div>
      <span class="demonstration">测试</span>
        <el-button style="margin-left:10px" size="mini" type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
        <el-button size="mini" type="" icon="el-icon-refresh" @click="handleReset">重置</el-button>
      <div>
          <span>已选择:{{dataClasses2.length}}人</span>
          <el-tag v-for="(item,index) in dataClasses2" :key="index" closable="" @close="closeTag(item)">{{item.label}}</el-tag>
      </div>
        <el-cascader-panel ref="mycas2" :options="options2" :props="props" v-model="data2" @change="getData" v-show="showEl"></el-cascader-panel>
        <el-checkbox-group v-model="checkList"  v-show="!showEl">
            <el-checkbox v-for="(item,index) in stuList" :key="index" :label="item.id" :value="item.id" @change="selectBox(item,$event)">{{item.name}}</el-checkbox>
      </el-checkbox-group>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      props: { multiple: true },
      dataClasses: [],
      checkList: [],
      data2: [],
      dataClasses2: [],
      stuList: [
        {
          id: 211,
          name: "小黄",
        },
        {
          id: 212,
          name: "小z",
        },
        {
          id: 213,
          name: "小z",
        },
      ],
      showEl: true,
      options2: [
        {
          value: "1",
          label: "一年级",
          children: [
            {
              value: 11,
              label: "一班",
              children: [
                {
                  value: 111,
                  label: "小明",
                },
                {
                  value: 112,
                  label: "小红",
                },
                {
                  value: 113,
                  label: "小率",
                },
                {
                  value: 114,
                  label: "小栏",
                },
                {
                  value: 115,
                  label: "小子",
                },
                {
                  value: 116,
                  label: "小白",
                },
                {
                  value: 117,
                  label: "小嘿",
                },
              ],
            },
            {
              value: 12,
              label: "二班",
              children: [
                {
                  value: 211,
                  label: "小1",
                },
                {
                  value: 212,
                  label: "小2",
                },
                {
                  value: 213,
                  label: "小3",
                },
                {
                  value: 214,
                  label: "小4",
                },
                {
                  value: 215,
                  label: "小5",
                },
                {
                  value: 216,
                  label: "小6",
                },
                {
                  value: 217,
                  label: "小7",
                },
              ],
            },
            {
              value: 13,
              label: "三班",
            },
            {
              value: 14,
              label: "四班",
            },
          ],
        },
        {
          value: "2",
          label: "二年级",
          children: [
            {
              value: 21,
              label: "一班",
            },
            {
              value: 22,
              label: "二班",
            },
            {
              value: 23,
              label: "三班",
            },
            {
              value: 24,
              label: "四班",
            },
          ],
        },
        {
          value: "3",
          label: "三年级",
        },
      ],
    };
  },

  created() {
    // 初始化展开
    this.$nextTick(() => {
      let node = this.$refs.mycas2.menus[0];
      this.$refs.mycas2.handleExpand(node, true);
      this.$refs.mycas2.handleExpand(node[0], true);
      this.$refs.mycas2.handleExpand(node[0].children[0], true);
    });
  },
  methods: {
    // 关闭标签时,取消节点的选择
    closeTag(item) {
      console.log(item);
      item.doCheck(false);
      this.$refs.mycas2.calculateMultiCheckedValue();
    },
    // 获取选择的叶子节点,根据层级过滤
    getData() {
      this.dataClasses2 = this.$refs.mycas2
        .getCheckedNodes()
        .filter((n) => n.level == 3);
    },

    // 查询
    handleQuery() {
      this.showEl = false;
    },

    // 重置
    handleReset() {
      this.showEl = true;
    },

    // 外部选择或者取消
    selectBox(item, value) {
      this.$refs.mycas2.getNodeByValue(item.id).doCheck(value);
      this.$refs.mycas2.calculateMultiCheckedValue();
    },
  },
};
</script>
<style scoped>
</style>

华裳绕指柔, 版权所有丨如未注明 , 均为原创|转载请注明vue Cascader 级联面板使用整理
喜欢 (11)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址