一、功能需求
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 ,只读会导致输入框输入功能失效。在此显然不适用,因为我们还需要继续添加成员,所以我也没有好的办法。欢迎有想法的小伙伴留言解决,在此膜拜各位大佬。
四、总结
以上内容只是简单实现该功能,只适用于页面初始化后的初步操作,在实际项目中,如果涉及到弹框显示,编辑内容回显,关闭弹框初始化默认值等操作时,可能会导致以上某些内容失效,小伙伴们可以根据实际情况进行优化,感谢大家!