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/...

相关推荐
一个处女座的程序猿O(∩_∩)O2 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
燃先生._.8 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
2401_8576009511 小时前
SSM 与 Vue 共筑电脑测评系统:精准洞察电脑世界
前端·javascript·vue.js
2401_8576009511 小时前
数字时代的医疗挂号变革:SSM+Vue 系统设计与实现之道
前端·javascript·vue.js
GDAL11 小时前
vue入门教程:组件透传 Attributes
前端·javascript·vue.js
轻口味11 小时前
Vue.js 核心概念:模板、指令、数据绑定
vue.js
2402_8575834911 小时前
基于 SSM 框架的 Vue 电脑测评系统:照亮电脑品质之路
前端·javascript·vue.js
java_heartLake12 小时前
Vue3之性能优化
javascript·vue.js·性能优化
ddd君3177413 小时前
组件的声明、创建、渲染
vue.js
前端没钱14 小时前
从 Vue 迈向 React:平滑过渡与关键注意点全解析
前端·vue.js·react.js