先提下背景:就是在测试的过程中,经常需要用到收货这个功能。在PC端下了采购单,再到APP去对应功能里,再输入好多个字段,上传图片等动作后,终于可以提交。
于是,我决定在平台上加个小工具,快捷收货,方便测试用。
那么,在收货操作中,要有收货人这个角色。为了更好的适用性,我决定做成一个搜索框,支持实时搜索人员。于是,从elementUI上找到了select选择器 远程搜索。
这里提一下,前端菜鸟怎么去用elementUI上的这些组件:
- 操作官方示例,感受组件的实际效果,确实是否满足你需求。
- 展开示例代码,关注使用的字段、方法等。
- copy示例代码,用你实际的数据、字段等去替换掉它,直到调试成功。
<template> <el-select v-model="value" multiple filterable remote reserve-keyword placeholder="请输入关键词" :remote-method="remoteMethod" :loading="loading"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </template> <script> export default { data() { return { options: [], value: [], list: [], loading: false, states: ["Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"] } }, mounted() { this.list = this.states.map(item => { return { value: `value:${item}`, label: `label:${item}` }; }); }, methods: { remoteMethod(query) { if (query !== '') { this.loading = true; setTimeout(() => { this.loading = false; this.options = this.list.filter(item => { return item.label.toLowerCase() .indexOf(query.toLowerCase()) > -1; }); }, 200); } else { this.options = []; } } } } </script>
从示例代码里,可以看出:
states
应该存放我后端接口返回的数据,示例里states是列表,我接口返回的也是列表,不过里面元素都是对象,每个对象里存着不同人的信息。mounted()
方法里面,是在渲染完成后,将states
里的列表数据,进一步处理成一个对象,用map()
返回一个新的列表,并且赋值给this.list
。- 最终在
remoteMethod(query)
方法里,根据输入的传参query,对this.list
里的数据进行过滤,返回出匹配的数据,赋值到this.options
,这样下拉列表就可以展示结果。
这里的.indexOf(query.toLowerCase()) > -1
,大于-1说明只要有就行,不论是不是开头也好,中间也好,或者结尾也好。比如搜“大周”,你输入“大”或者“周”,都可以搜到。
赶紧参考官方示例,满心欢喜地开始修改代码:
// mounted()内容 mounted() { this.list = this.states.map(item => { return { value: `${item.id}`, label: `${item.role_name}-${item.ad_real_name}` }; }); },
// method()里内容 remoteMethod(query) { if (query !== '') { this.loading = true; this.$axios.post("/api/receiveGoodsQuickly/getWmsAdminInfo", { "ad_real_name": query, "mchid": 6001 }).then((response) => { this.states = response.data['content']; }); setTimeout(() => { this.loading = false; this.options = this.list.filter(item => { return item.label.toLowerCase() .indexOf(query.toLowerCase()) > -1; }); }, 1000); } else { this.options = []; } }, 。。。。。。
可是实际执行效果是这样的:
我输入第一次“张三”,没结果。当我再输入一次“张三”,返回出了对应的结果。
我继续输入“李四”,仍然没结果,再输入一次“李四”,结果出来了......
后来发现,还是不能直接套用官方示例的,因为示例代码是直接初始化了数据在states
里,而我实际是要去请求后端接口才能拿到数据。如此一来,当我第一次调用到remoteMethod
方法,实际上this.list是null。当我第二次调用的时候,其实出现的是上一次的查询结果。
最终,找到了解决办法,就是在computed
增加处理步骤,computed起到侦听的作用,这样可以立即得到处理好的数据。
computed: { listSet() { return this.states.map(item => { return { value: `${item.id}`, label: `${item.role_name}-${item.ad_real_name}` }; }); } },
setTimeout(() => { this.loading = false; this.options = this.listSet.filter(item => { // 这里的this.list,换为this.listSet return item.label.toLowerCase() .indexOf(query.toLowerCase()) > -1; }); }, 1000);
调试通过,搜索结果实时展示。