elemenUI 2.x:下拉选择器中一些属性的配合使用

只提供大致思路,大量玩法等你开发【doge】

1、单选带搜索功能(自定义搜索)

例如,我需要实现一个功能:搜索指定姓开头的所有名字(中文)。下面我就直接省略了表单form组件了哈(一般像这类选择框、输入框等组件都是写在el-form中的)。

官方提供了一个属性:filterable,添加它就可以直接实现模糊查询的效果,不过我们的目的是实现查询某个姓开头的所有名字这个查询逻辑,所以要自定义一个方法,因此我们要用到官方提供的另一个属性:filter-methodfilter-method为一个Function类型,它会在输入值发生变化时调用,参数为当前输入值。当然,在使用这个属性时,filteralbe属性也不能丢。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- 引入vue -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> -->
    <script src="../vue/vue.js"></script>
    <!-- 引入样式 -->
    <link
      rel="stylesheet"
      href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
    />
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>

    <!-- 浏览器引入mockjs文件 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/Mock.js/1.0.0/mock.js"></script>

    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <template>
        <!-- 匹配指定姓的全部姓名 -->
        <!-- last name是姓的意思 -->
        <el-select
          filterable
          v-model="searchValue"
          placeholder="请输入姓名中的姓(中文)"
          :filter-method="getNameByLastName"
          clearable
        >
          <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          >
          </el-option>
        </el-select>
      </template>
    </div>
    <script>
      // mock模拟数据
      var Random = Mock.Random;
      // 生成一个包含20个对象类型的元素的数组
      let data = Mock.mock({
      
      
        "list|10": [
          {
      
      
            "value|+1": 0,
            label: () => {
      
      
              return Random.cname();
            },
          },
        ],
      });

      console.log(data);
      Vue.config.productionTip = false;

      new Vue({
      
      
        el: "#app",
        data() {
      
      
          return {
      
      
            searchValue: "",
            options: data.list,
          };
        },
        methods: {
      
      
          // 重新定义搜索规则:获取指定姓相关的全部姓名
          getNameByLastName(val) {
      
      
            this.searchValue = val;
            if (val) {
      
      
              this.options = data.list.filter((item) => {
      
      
                console.log(item.label.split("")[0]);
                return item.label.split("")[0] == val;
              });
            } else {
      
      
              this.options = data.list;
            }
          },
        },
      });
    </script>
  </body>
</html>

效果如下:
请添加图片描述

2、下拉多选+远程搜索

如标题所示,我们将实现两个功能,多选+远程搜索,多选将用到multiple属性启用多选,此时v-model接收的是一个数组,远程搜索将用到filterable开启查询)属性和remote开启远程搜索)属性,并在使用时将两者设置为true,同时传入一个remote-method属性,该属性接收一个Function,会在输入值发生变化时调用参数表示当前输入的值。此外,如果数据比较多,那么远程搜索的展示就会很慢,所以我们需要loading属性来显示数据未展示时的效果。

下面,我们将实现功能,不过在那之前,我们得先知道,后端传到前端的数据的格式不一定就会是options需要的形式(options[{value:xxx,lable:xxx}]), 有可能就只是一个普通的字符串数组,所以我们需要转换格式。此外,下面的方式并未调用远程接口,只是简单的对本地数据进行操作,所以会用到定时器函数模拟获取远程数据时的延迟效果。

那么,接下来,我们展示代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- 引入vue -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> -->
    <script src="../vue/vue.js"></script>
    <!-- 引入样式 -->
    <link
      rel="stylesheet"
      href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
    />
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>

    <!-- 浏览器引入mockjs文件 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/Mock.js/1.0.0/mock.js"></script>

    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <template>
        <el-select
          multiple
          filterable
          remote
          :remote-method="remoteMethod1"
          v-model="values1"
          :loading="loading1"
          placeholder="请输入姓名"
          clearable
          no-data-text="没有这个名字哦"
        >
          <el-option
            v-for="item in options1"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          >
          </el-option>
        </el-select>
        &nbsp; &nbsp; &nbsp; &nbsp;
        <el-select
          multiple
          filterable
          remote
          :remote-method="remoteMethod2"
          v-model="values2"
          :loading="loading2"
          placeholder="请输入姓名"
          clearable
          no-data-text="没有这个名字哦"
        >
          <el-option
            v-for="item in options2"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          >
          </el-option>
        </el-select>
      </template>
    </div>
    <script>
      // mock模拟数据
      var Random = Mock.Random;

      // 生成一个包含20个对象类型的元素的数组
      let data1 = Mock.mock({
      
      
        "list|20": [
          {
      
      
            "value|+1": 0,
            label: "@cname",
          },
        ],
      });

      // 生成一个包含20个字符串元素的数组
      let data2 = Mock.mock({
      
      
        "list|20": [
          () => {
      
      
            return Random.cname();
          },
        ],
      });

      Vue.config.productionTip = false;

      new Vue({
      
      
        el: "#app",
        data() {
      
      
          return {
      
      
            values1: [],
            values2: [],
            loading1: false,
            loading2: false,
            options1: [],
            options2: [],
            list: [],
          };
        },
        mounted() {
      
      
          this.options1 = data1.list;
          console.log(this.options1, "this.options1 ===========");

          // 将字符串数组转为指定对象形式的数组{value:xxx,label:xxx}
          this.list = data2.list.map((item, index) => {
      
      
            return {
      
       value: index, label: item };
          });
          this.options2 = this.list;

          console.log(data2.list, "data2.list ===============");
          console.log(this.options2, "this.options2 ==============");
        },
        methods: {
      
      
          remoteMethod1(query) {
      
      
            if (query !== "") {
      
      
              this.loading1 = true;
              setTimeout(() => {
      
      
                this.loading1 = false;

                // 过滤出匹配的数据
                this.options1 = data1.list.filter((item) => {
      
      
                  return (
                    item.label.toLowerCase().indexOf(query.toLowerCase()) > -1
                  );
                });
              }, 2000);
            } else {
      
      
              this.options1 = [];
            }
          },

          remoteMethod2(query) {
      
      
            if (query !== "") {
      
      
              this.loading2 = true;
              setTimeout(() => {
      
      
                this.loading2 = false;
                
                // 过滤出匹配的数据
                this.options2 = this.list.filter((item) => {
      
      
                  return (
                    item.label.toLowerCase().indexOf(query.toLowerCase()) > -1
                  );
                });
              }, 2000);
            } else {
      
      
              this.options2 = [];
            }
          },
        },
      });
    </script>
  </body>
</html>

在这里插入图片描述

补充:如果不想一开始就显示出下拉选项,那么在上述代码的mounted钩子中,你可以不对options进行赋值,这样就能达到想要的效果了。

3、下拉多选+有默认选项

例如,我们想要options.value=3的选项默认展示

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- 引入vue -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> -->
    <script src="../vue/vue.js"></script>
    <!-- 引入样式 -->
    <link
      rel="stylesheet"
      href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
    />
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>

    <!-- 浏览器引入mockjs文件 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/Mock.js/1.0.0/mock.js"></script>

    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <template>
        <el-select
          multiple
          filterable
          remote
          :remote-method="remoteMethod"
          v-model="values"
          :loading="loading"
          placeholder="请输入姓名"
          clearable
          no-data-text="没有这个名字哦"
        >
          <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          >
          </el-option>
        </el-select>
      </template>
    </div>
    <script>
      // mock模拟数据
      var Random = Mock.Random;

      // 生成一个包含20个对象类型的元素的数组
      let data = Mock.mock({
      
      
        "list|20": [
          {
      
      
            "value|+1": 0,
            label: "@cname",
          },
        ],
      });

      console.log(data, "data ==========");

      Vue.config.productionTip = false;

      new Vue({
      
      
        el: "#app",
        data() {
      
      
          return {
      
      
            values: [],
            loading: false,
            options: [],
          };
        },
        mounted() {
      
      
          // 什么时候需要重新置为空数组? => 如果打开某个组件,这个组件上次打开时的数据没有被清除,同时这次数据又被添加上去的时候
          //   this.values = [];
          //   this.options = [];

          data.list.forEach((item) => {
      
      
            if (item.value == 3) {
      
      
              this.values.push(item.value);
              /* 
              注意:一定要加下面这行代码给options赋值,
              否则,到时选择项显示的将会是value的值,而不是label的值
              */
              this.options.push(item);
            }
          });
        },
        methods: {
      
      
          remoteMethod(query) {
      
      
            if (query !== "") {
      
      
              this.loading = true;
              setTimeout(() => {
      
      
                this.loading = false;

                // 过滤出匹配的数据
                this.options = data.list.filter((item) => {
      
      
                  return (
                    item.label.toLowerCase().indexOf(query.toLowerCase()) > -1
                  );
                });
              }, 1000);
            } else {
      
      
              this.options = [];
            }
          },
        },
      });
    </script>
  </body>
</html>

在这里插入图片描述

4、下拉多选+默认禁用

要实现的效果如图:
请添加图片描述

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- 引入vue -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> -->
    <script src="../vue/vue.js"></script>
    <!-- 引入样式 -->
    <link
      rel="stylesheet"
      href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
    />
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>

    <!-- 浏览器引入mockjs文件 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/Mock.js/1.0.0/mock.js"></script>

    <title>Document</title>
    <style>
      /* 消除tag标签后面的x */
      /* .el-select .el-select__tags i {
        display: none;
      } */
    </style>
  </head>
  <body>
    <div id="app">
      <template>
        <el-select
          multiple
          filterable
          remote
          :remote-method="remoteMethod"
          v-model="values"
          :loading="loading"
          placeholder="请输入姓名"
          clearable
          no-data-text="没有这个名字哦"
          @clear="clearName"
          @remove-tag="removeTag"
        >
          <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value"
            :disabled="item.disabled"
          >
          </el-option>
        </el-select>
      </template>
    </div>
    <script>
      // mock模拟数据
      var Random = Mock.Random;

      // 生成一个包含20个对象类型的元素的数组
      let data = Mock.mock({
      
      
        "list|20": [
          {
      
      
            "value|+1": 0,
            label: "@cname",
          },
        ],
      });

      console.log(data, "data ==========");

      Vue.config.productionTip = false;

      new Vue({
      
      
        el: "#app",
        data() {
      
      
          return {
      
      
            values: [],
            loading: false,
            options: [],
          };
        },
        mounted() {
      
      
          // 什么时候需要重新置为空数组? 
          // => 如果打开某个组件,这个组件上次打开时的数据没有被清除,
          // 同时这次数据又被添加上去的时候
          //   this.values = [];
          //   this.options = [];

          // 第一种方式:
          data.list.forEach((item) => {
      
      
            if (item.value == 3) {
      
      
              this.values.push(item.value);
              /*
                   注意:一定要加下面这行代码给options赋值,
                   否则,到时选择项显示的将会是value的值,而不是label的值
                   */
              this.options.push(item);
              item.disabled = true; // 设置选项不可用
            }
          });

          // 第二种实现方式:
          //   this.values = [3]; // 要禁用的选项放在数组中
          //   data.list.forEach((item) => {
      
      
          //     this.values.forEach((val) => {
      
      
          //       if (item.value === val) {
      
      
          //         item.disabled = true;
          //         this.options.push(item);
          //       }
          //     });
          //   });
        },

        methods: {
      
      
          // 远程查询
          remoteMethod(query) {
      
      
            if (query !== "") {
      
      
              this.loading = true;
              setTimeout(() => {
      
      
                this.loading = false;

                // 过滤出匹配的数据
                this.options = data.list.filter((item) => {
      
      
                  return (
                    item.label.toLowerCase().indexOf(query.toLowerCase()) > -1
                  );
                });
              }, 1000);
            } else {
      
      
              this.options = [];
            }
          },

          // 下拉框所选数据的清除(不清除默认值)
          clearName() {
      
      
            // 只要让默认选项的value值一直存在即可避免被清除
            this.values = [3];
          },

          /**
           * @description: 移除tag时触发的事件
           * @param item 在这里指的是所选值的value值,也就是options数组下面每一个对象的value值
           */
          removeTag(item) {
      
      
            // 当要删除的tag的value值不等于3时
            if (item !== 3) {
      
      
              console.log(item);
            }
            // 当要删除的tag的value等于3时,让它不能删除默认值
            else {
      
      
              this.values = [3];
              /*
              我这保留默认项(默认项不能被删除)一直没想到什么好办法,
              只能让this.values重新进行赋值,让他达到看起来没被删除的效果,
              有懂得大佬可以提供下思路吗
              */
            }
          },
        },
      });
    </script>
  </body>
</html>

其他待补充doge

猜你喜欢

转载自blog.csdn.net/lalala_dxf/article/details/128718498