vue+ElementUI实现下拉分级菜单:el-select嵌套el-tree树形控件实现下拉树效果(附带模糊查询搜索功能)

先上完工效果图:

输入框搜索选项功能:可以根据需求决定是否保留

js 复制代码
<template>
  <div class="about">
  	// select框绑定的值是selectVal,也就是treeData里的value
    <el-select
      v-model="selectVal"
      placeholder="请选择..."
      size="mini"
      clearable
      ref="select"
      style="width: 300px"
    >
      // 设置一个input框用作模糊搜索选项功能
      <el-input
        class="input"
        placeholder="此处键入'关键词'搜索查询"
        prefix-icon="el-icon-search"
        v-model="treeFilter"
        size="mini"
        clearable
      ></el-input>
      // 设置一个隐藏的下拉选项,选项显示的是汉字label,值是value
      // 如果不设置一个下拉选项,下面的树形组件将无法正常使用
      <el-option hidden key="id" :value="selectVal" :label="selectName">
      </el-option>
      // 设置树形控件
      <el-tree
        :data="treeData"
        :props="defaultProps"
        @node-click="handleNodeClick"
        :expand-on-click-node="false"
        :check-on-click-node="true"
        ref="tree"
        node-key="id"
        :default-expand-all="true"
        :filter-node-method="filterNode"
      >
      // @node-click:树形控件选项点击事件
      // :expand-on-click-node:使树形控件只有点箭头图标的时候才会展开或者收缩节点,为false则点文字直接选中该项
      // :check-on-click-node:是否在点击节点的时候选中节点,当选项为复选框时有用,这个属性可以删除
      // :default-expand-all:默认展开所有节点
      // :filter-node-method:实现搜索功能的筛选方法
      
        <span slot-scope="{ data }">  
        //选项用插槽来显示,匹配搜索功能,并方便增加tag标签需求
          <span>{{ data.label }}</span>
          <el-tag
            size="mini"
            style="margin: 0 10px"
            v-show="filterorgType(data.tag)"
            >{{ filterorgType(data.tag) }}</el-tag
          >
        </span>
      </el-tree>
    </el-select>
  </div>
</template>

<script>
export default {
  name: "el-select-tree",
  data() {
    return {
      selectVal: "", // select框的绑定值
      selectName: "", // select框显示的name
      treeFilter: "", // 搜索框绑定值,用作过滤
      // 树形控件数据
      treeData: [
        {
          value: "1",
          label: "一级 1菈妮",
          tag: "wife",
          children: [
            {
              value: "1-1",
              label: "二级 1-1",
              children: [
                {
                  value: "1-1-1",
                  label: "三级 1-1-1",
                },
              ],
            },
          ],
        },
        {
          label: "一级 2",
          value: "2",
          children: [
            {
              value: "2-1",
              label: "二级 2-1",
              children: [
                {
                  value: "2-1-1",
                  label: "三级 2-1-1",
                },
              ],
            },
            {
              value: "2-2",
              label: "二级 2-2",
              children: [
                {
                  value: "2-2-1",
                  label: "三级 2-2-1鸡腿",
                  tag: "princess",
                },
              ],
            },
          ],
        },
        {
          value: "3",
          label: "一级 3",
          children: [
            {
              value: "3-1",
              label: "二级 3-1",
              children: [
                {
                  value: "3-1-1",
                  label: "三级 3-1-1",
                },
              ],
            },
            {
              value: "3-2",
              label: "二级 3-2艾尔登法环",
              tag: "yyds",
              children: [
                {
                  value: "3-2-1",
                  label: "三级 3-2-1",
                },
              ],
            },
          ],
        },
      ],
      defaultProps: {
        children: "children",
        label: "name",
      },
      // 标签数组
      tagList: [
        { value: "wife", label: "老婆" },
        { value: "princess", label: "小公主" },
        { value: "yyds", label: "天下第一" },
      ],
    };
  },
  watch: {
    // 搜索过滤,监听input搜索框绑定的treeFilter
    treeFilter(val) {
      this.$refs.tree.filter(val);
      // 当搜索框键入值改变时,将该值作为入参执行树形控件的过滤事件filterNode
    },
  },
  methods: {
    // 结构树点击事件
    handleNodeClick(data) {
      this.selectVal = data.value; // select绑定值为点击的选项的value
      this.selectName = data.label; // input中显示值为label
      this.treeFilter = ""; // 点击后搜索框清空
      this.$refs.select.blur(); // 点击后关闭下拉框,因为点击树形控件后select不会自动折叠
    },
    // 模糊查询(搜索过滤),实质为筛选出树形控件中符合输入条件的选项,过滤掉其他选项
    filterNode(value, data) {
      if (!value) return true;
      let filterRes = data.label.indexOf(value) !== -1;
      return filterRes;
    },
    // 选项卡标签(可忽略,增值迭代需求)
    filterorgType(val) {
      let arr = this.tagList.filter((item) => {
        return item.value == val;
      });
      return arr.length ? arr[0].label : "";
    },
  },

  mounted() {},
};
</script>

<style scoped>
.input {
  width: 260px;
  margin: 10px;
}
</style>

来源:blog.csdn.net/vvv3171071/...

相关推荐
w风雨无阻w2 小时前
Vue3 学习笔记(十一)Vue生命周期
javascript·vue.js·前端框架·vue3
清清ww2 小时前
【vue】13.深入理解递归组件
前端·javascript·vue.js
清清ww2 小时前
【vue】09.computer和watch的使用
前端·javascript·vue.js
sometime`something3 小时前
飞书文档解除复制限制
vue.js
Iqnus_1233 小时前
vue下载安装
前端·vue.js·笔记
tryCbest3 小时前
Nodejs安装配置及创建vue项目
vue.js·node.js
清灵xmf4 小时前
UI 组件的二次封装
前端·javascript·vue.js·element-plus
聪明的墨菲特i4 小时前
Vue组件学习 | 二、Vuex组件
前端·vue.js·学习·前端框架·1024程序员节
x原力觉醒5 小时前
uniapp跨域问题,在开发环境中配置
javascript·vue.js·uni-app