vue + Element ui 实现 select 组件的远程搜索功能及默认值不可删除功能

6,242 阅读4分钟

一、功能需求

1、给定一组员工信息(项目实战中,可通过接口获取),要求输入员工 oa ,自动检索到员工的 name ,选择并添加(可多选)。

2、对于默认的员工(例如管理员),不可进行删除。

二、实现依赖

  • vue

  • element ui 的 select 组件的远程搜索功能(具体可参考官方

三、实现方式

1、根据输入的oa,添加员工 name(可多选)

1.1 在data中定义员工信息列表 userList ,可选项 options ,懒加载 loading 及表单数据 form。

      options: [],
      loading: false,
      userList: [
        {
          id: 1,
          oa: '10001',
          name: '管理员'
        },
        {
          id: 2,
          oa: '23342',
          name: '小红'
        },
        {
          id: 3,
          oa: '51675',
          name: '小明'
        },
        {
          id: 4,
          oa: '39800',
          name: '张三'
        },
        {
          id: 5,
          oa: '65002',
          name: '李四'
        }
      ],
      form: {
        users: []//接收已选的员工的oa
      },

1.2 页面渲染及参数(options ,userList ,loading)绑定。

      <el-form
        ref="form"
        :model="form"
        label-width="100px"
        :rules="rules"
      >
        <el-form-item label="成员" prop="users">
          <el-select
            v-model="form.users"
            multiple
            filterable
            remote
            :reserve-keyword="false"
            default-first-option
            placeholder="请添加成员"
            style="width:100%"
            :remote-method="remoteMethod"
            :loading="loading"
          >
            <el-option
              v-for="item in options"
              :key="item.oa"
              :label="item.name"
              :value="item.oa"
            />
          </el-select>
        </el-form-item>
       </el-form>

1.3 在 methods 实现方法,主要是 remoteMethod 方法。

只要oa中有包含输入的字符,就会返回所有符合条件的员工信息列表并赋值给 options。

    remoteMethod(query) {
      if (query !== '') {
        this.loading = true
        setTimeout(() => {
          this.loading = false
          this.options = this.userList.filter(item => {
            return item.oa.toLowerCase()
              .indexOf(query.toLowerCase()) > -1
          })
        }, 100)
      } else {
        this.options = []
      }
    },

1.4 效果展示。

2、设置默认值且默认值不可删除

解决思路:要实现默认值不可删除,首先默认值的 tag 不可删除,包括隐藏关闭按钮及屏蔽键盘的删除操作;其次默认值对应的 options 选项不可选择。下面是具体的实现方式:

2.1 将管理员设置为默认值。

 created() {
    // 将管理员设置为默认值
    this.form.users.push('10001')
    // 通过oa获取name,页面回显用
    this.remoteMethod('10001')
 },

2.2 在 main.js 中自定义指令 v-defaultSelect 用于控制关闭按钮的显示与隐藏。

Vue.directive('defaultSelect', {
  // 具体请戳:https://cn.vuejs.org/v2/guide/custom-directive.html
  inserted(el, bindings, vnode) {
    // values: v-model绑定值
    // options:下拉选项
    // prop:对应options中的value属性
    // defaultProp:默认值判断属性
    // defaultValue:默认值判断值
    const [values, options, prop, defaultProp, defaultValue] = bindings.value

    // 需要隐藏的标签索引
    const indexs = []
    const tempData = values.map(a => options.find(op => op[prop] === a))
    tempData.forEach((a, index) => {
      if (a[defaultProp] === defaultValue) indexs.push(index)
    })

    const dealStyle = function(tags) {
      tags.forEach((el, index) => {
        if (indexs.includes(index) && ![...el.classList].includes('select-tag-close-none')) {
          el.classList.add('none')
        }
      })
    }

    // 设置样式,隐藏close icon
    const tags = el.querySelectorAll('.el-tag__close')
    if (tags.length === 0) {
      // 初始化tags为空处理
      setTimeout(() => {
        const tagTemp = el.querySelectorAll('.el-tag__close')
        dealStyle(tagTemp)
      })
    } else {
      dealStyle(tags)
    }
  }
})

2.3 在 App.vue 中定义隐藏关闭按钮的样式 none。

<style>
.none{
  display:none !important;
}
</style>

2.4 userList 中新增参数 disabled 用来控制 options 选项的不可选择, true 表示不可选,false 表示可选。

      userList: [
        {
          id: 1,
          oa: '10001',
          name: '管理员',
          disabled: true
        },
        {
          id: 2,
          oa: '23342',
          name: '小红',
          disabled: false
        },
        {
          id: 3,
          oa: '51675',
          name: '小明',
          disabled: false
        },
        {
          id: 4,
          oa: '39800',
          name: '张三',
          disabled: false
        },
        {
          id: 5,
          oa: '65002',
          name: '李四',
          disabled: false
        }
      ],

2.5 在当前页面自定义 options 选项不可选择以及可选择时的样式。

<style>
.class1{
  color: #c3cfdb !important;/* 不可选 */
}
.class2{
  color: #409EFF !important;/* 可选 */
}
</style>

2.6 页面渲染及标签属性绑定。

  • 新增 v-defaultSelect 指令的绑定(绑定到 el-select 标签):主要实现默认值标签关闭按钮的隐藏功能。

  • 新增 disabled 属性的绑定(绑定到 el-option 标签):主要实现默认值在 options 选项中的不可选择功能。

  • 新增 class 属性的绑定(绑定到 el-option 标签):主要通过判断 disabled 为 true (默认值不可选)时,选项置灰,否则不置灰。

      <el-form
        ref="form"
        :model="form"
        label-width="100px"
        :rules="rules"
      >
        <el-form-item style="margin-bottom: 20px;" label="成员" prop="users">
          <el-select
            v-model="form.users"
            v-defaultSelect="[form.users,options,'oa','disabled',true]"
            multiple
            filterable
            remote
            :reserve-keyword="false"
            default-first-option
            placeholder="请添加成员"
            style="width:100%"
            :remote-method="remoteMethod"
            :loading="loading"
          >
            <el-option
              v-for="item in options"
              :key="item.oa"
              :label="item.name"
              :value="item.oa"
              :disabled="item.disabled"
              :class="item.disabled === true ? 'class1' : 'class2'"
            />
          </el-select>
        </el-form-item>
      </el-form> 
    

2.7 效果展示

以上基本实现了默认值不可删除的功能,但是测试时发现当鼠标光标在输入框中时,使用键盘的 “Backspace” 仍然可以将默认值删除,显然不对。

解决思路是将键盘的删除功能进行禁用,但是不起作用。原因似乎是每一个选中项都是一个个单独的 span 标签,而键盘操作是针对 input 框,所以不生效,而且就算生效,也需要用到只读属性 readonly ,只读会导致输入框输入功能失效。在此显然不适用,因为我们还需要继续添加成员,所以我也没有好的办法。欢迎有想法的小伙伴留言解决,在此膜拜各位大佬。

四、总结

以上内容只是简单实现该功能,只适用于页面初始化后的初步操作,在实际项目中,如果涉及到弹框显示,编辑内容回显,关闭弹框初始化默认值等操作时,可能会导致以上某些内容失效,小伙伴们可以根据实际情况进行优化,感谢大家!

参考文章:blog.csdn.net/qq_36356218…