一年前的项目记不太清了 因为要准备面试所以回忆一下
需求:
当且仅当用户在输入框内输入 ` 这个符号时才会触发远程搜索,用户选择下拉框内值后,将这个值附加在用户原来输入的内容的后面
难点是:
这个需求原本有人做过,当时的需求是,把下拉框值赋到光标之后,但是代码有问题,导致用户在某一行el- autocomplete输入时,光标会自动跳到另一行el- autocomplete上
bug原因是:
由于本页面需要实现:用户先选择要输入的内容的格式(如redis,pb等,格式不同后续要输入的值的类型或数量也不同),页面会根据用户想输入的格式,动态生成不同的输入框供用户输入.本页面的所有输入框都是由v-if(或者是v-show?记不清了)控制有无的,所以每次重选格式(还是怎么着来着?我真的忘了),由于diff算法,vue会复用部分元素(没有key且元素一样),dom树会打补丁.
原来那个哥们用了el.foucs()将远程搜索值赋给光标所在的位置.而这个光标所在的位置又是通过dom拿的,这个拿到的dom值其实是页面刚进来时拿到的,后续变动没有更新到(好像是这个原因,反正是拿到的dom值不对,本来该赋给这一行的值赋到另一行去了),所以有时候光标会乱飞
我的改法:
先debug,发现是由于diff算法 dom树的原因,尝试绑定key,不改远程搜素部分代码,发现不行.最后没有用原来的远程搜索代码,而是自己重写了一个,完美解决
忘了具体怎么写的了,似乎是改的http://t.csdnimg.cn/AvMNU这位博主的代码.凭记忆回现一下,只是提供一下思路,并不是实际的代码
<el-autocomplete
class="inline-input"
v-model="inputValue"
:fetch-suggestions="querySearch"
placeholder="请输入内容"
@select="handleAcademySelect"
:trigger-on-focus="false"//true:输入框获取焦点时就触发
></el-autocomplete>
//输入框获取焦点时调用的方法,cb是个回调函数
querySearch(queryString, cb) {
if(queryString!='') {//输入框中有值
if (queryString.charAt(value.length - 1) === '`') { //如果输入框内的值的最后一个字符是·,执行模糊搜索
this.load(queryString, (data) => {//this.load:向后端发送请求,请求返回值赋给data
var results = queryString ? data.filter(this.createStateFilter(queryString)) : data;
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
cb(results);//回调函数cb返回筛选出的结果数据到输入框下面的输入列表
}, 5000*Math.random());
})
}
},
createStateFilter(queryString) {//不区分大小写的搜索
return (state) => {
return (state.value.toLowerCase().indexOf(queryString.toLowerCase())>-1);
};
},
handleAcademySelect(item) {//抄的原博主的代码,忘记我原本是怎么写的了
this.searchForm.academyId=item.name;
},
另外,需求要求把下拉框内的值附加到用户原输入值的后面,而不是替换用户的原输入值.
用到了slot插槽,由于这段比较简单且我比较困就不多写了.参考的这位博主的文章http://t.csdnimg.cn/ZUwSe
// template
<el-autocomplete
v-model="ele.exp"
:fetch-suggestions="querySearch"
placeholder="请输入内容"
value-key="newTip"//实际绑定的是newtip,即用户先前输入的值拼接tip值
:trigger-on-focus="false"
>
<template slot-scope="{ item }">
<div>{{ item.fulltip }}</div>//下拉框中显示的是fulltip
</template>
</el-autocomplete>
//data
restaurants: [
{
tip: "Plan",
fulltip: "Plan : {}",
},
],
querySearch(queryString, cb) {
// , 监测特殊符号
let len = queryString.length;
if (queryString.lastIndexOf(",") == len - 1;) {
var results = this.restaurants;
// 给数据新增一个newTip字段,然后value-key时绑定新的字段,而slot插槽中插入的是显示的值,所以虽然显示的是fulltip,但是当选中的时候,其实绑定的是newTip字段
results.map(item => {
//newtip是用户先前输入的值拼接tip值
item.newTip = `${queryString}${item.tip}`
})
// 调用 callback 返回建议列表的数据
cb(results);
} else {
cb([]);
}
},
不过其实这个代码也没有实现把下拉框的值赋到光标之后,而是直接赋到原输入值后面了,但是mentor说用户感知不到,所以收工.
如果想实现赋到光标之后的话,估计还要监听鼠标焦点事件,如<el-input @blur=“handleInputBlur”></el-input,或者this.$refs.myInput.focus();(这一步在我的项目中似乎又要用到dom了,可能是因为这个原因我才没实现把值赋到光标之后)拿到光标在输入内容中的位置index,然后 this.formulaValue=str.slice(0, index) + flg + str.slice(index);
参考这位博主的文章http://t.csdnimg.cn/uZ7Cq