vue3笔记(17-1)el-select搜索

本篇记录el-select一般搜索和远程搜索。

搜索基础用法

添加 filterable 关键字即可实现过滤(也可理解为组件自带的本地搜索),注意:只有添加了该关键词才能输入。multiple 用于实现多选,这里要注意的是加了multiple 之后,v-model 初始化必须是[],若使用 ‘’ 空字符串,在有弹窗的情况下,则会出现弹窗打开就执行了检验,出现了红色错误提示。

1
2
3
4
5
6
7
<el-select
v-model="roleForm.users"
multiple
filterable
>
<el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>

远程搜索

远程搜索添加remote关键字,使用remote-method添加搜索方法,默认传参为输入值,通过输入值进行搜索。

1
2
3
4
5
6
7
8
<el-select
v-model="roleForm.users"
multiple
filterable
:loading="loading"
remote
:remote-method="remoteMethod"
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const getDataUser = (data?: any) => {
let params = data || {}
getUsers(params)
.then((res) => {
const { data, data2, status, msg } = res
if (status == 'ok') {
state.userList = data
} else {
console.log(msg)
}
})
.catch((error) => {
console.log(error)
})
}

const loading = ref(false)
const remoteMethod = async (query: string) => {
if (query) {
loading.value = true
await getDataUser({ name: query, p: 1, pageSize: 10 })
loading.value = false
} else {
await getDataUser({ p: 1, pageSize: 10 })
}
}

远程获取所有数据,前端实现本地搜索

default-first-option 属性表示在输入框按下回车,选择第一个匹配项,配合 filterable 使用;filter-method 用户过滤方法。

1
2
3
4
5
6
7
8
9
<el-select
v-model="roleForm.users"
multiple
filterable
:filter-method="dataFilter"
default-first-option
>
<el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 初始化时state.userListAll存储所有用户信息
const dataFilter = (val) => {
if (val) { // 搜索框有值,本地过滤所有name含有相同字符的选项
state.userList = state.userListAll.filter((item) => {
if (item && !!~item.name.indexOf(val)) {
return true
}
})
} else { // 搜索框为空,默认获取列表前十个选项
getItems(1)
}
}

const getItems = (flag?: number) => {
if (flag) {
dataList.user.p = flag
}
let num = ~~dataList.user.p * ~~dataList.user.pageSize
state.userList = state.userListAll.filter((item, index, arr) => {
if (item) {
return index < num
}
})
}

懒加载

如果初始化数据过多,可能会造成页面卡顿,这里尝试懒加载

1
2
3
4
5
6
7
8
<el-select
v-model="roleForm.users"
multiple
filterable
v-loadmore="loadmore"
>
<el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const vLoadmore = {
mounted(el, binding) {
const SELECTWRAP_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
SELECTWRAP_DOM.addEventListener('scroll', function () {
const condition = this.scrollHeight - this.scrollTop <= this.clientHeight
if (condition) {
binding.value()
}
})
}
}

const loadmore = () => {
dataList.user.p++
getItems() //类似于分页查询
}

运行时控制台报错了!
loadmore error
经过检查,发现是没有找到DOM,猜测方法执行时DOM渲染还没有完成。
因为这个组件是在 dialog 中初始化,猜测可能是 v-if 导致,先尝试将组件移除 dialog 来测试,结果还是报错。。。
再尝试在组件 onMounted 时给 loadmore 赋值,想法完全错误!指令不能这么写,必须写一个全局常量。自定义指令自身的 mounted 已经代表了在挂载的组件渲染完成之后执行。
接着打印 el 的值,发现 el-select 节点中没有 el-select-dropdown …查阅很多资料,大家好像都没遇到这个问题???

点击加载更多

没办法,手写一个点击加载更多!放在 el-option 下方:

1
2
3
4
<el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id" />
<div v-if="user.p * user.pageSize < userTotal" @click="loadmore" class="load-more">
点击加载更多
</div>

点击加载更多

防抖节流

防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效

防抖debounce在连续的事件,只需触发一次回调的场景有:

  1. 搜索框搜索输入。只需用户最后一次输入完,再发送请求
  2. 手机号、邮箱验证输入检测
  3. 窗口大小resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。

节流throttle在间隔一段时间执行一次回调的场景有:

  1. 滚动加载,加载更多或滚到底部监听
  2. 搜索框,搜索联想功能