最近在使用iview重構老項目頁面代碼的時候,發現老項目有部分下拉框既可以編輯又可以選擇下拉框自帶的內容,找了找iview的select組件,發現並沒有一個類似的功能。
最接近我的需求的,可能是設置select的filterable屬性開啟搜索模式,但是每次輸入新的內容,鼠標一離開不是被清空,就是選中之前選擇的一項,故放棄。
后來又看到iview4.0的版本加了一個allow-create屬性,拿給老大看了下,他覺得太麻煩了,不夠簡潔,首先是必須輸完自定義的內容后,一定要點下圖的箭頭或者按回車,才能將內容加到列表。
另外就是覺得一定要把自定義的內容加到列表中,總覺得不舒服(不是我覺得啊),因此放棄。

對select抱有一絲希望的試了試,出了很多問題,最后放棄了用select組件來做。
后邊使用select也實現了該功能,可以查看我下一篇隨筆: https://www.cnblogs.com/mayiaction/p/12066923.html
后邊發現 auto-complete 組件很簡潔,在其基礎上做了一些改動,最終完成了這個要求,由於考慮到了模糊查詢的功能,由於做法的限制,拋棄了iview該組件自帶的模糊搜索,所以代碼復雜了點。
代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="http://unpkg.com/iview/dist/styles/iview.css">
<script type="text/javascript" src="http://vuejs.org/js/vue.min.js"></script>
<script type="text/javascript" src="http://unpkg.com/iview/dist/iview.min.js"></script>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<style type="text/css">
#app{padding: 32px;}
[myfocus]{
color: #2d8cf0;
background: #f3f3f3;
}
</style>
</head>
<body>
<div id="app">
<auto-complete
ref = "test"
v-model="nowLabel"
@on-change="changeSel"
@on-select="selectSel"
style="width:200px" icon="ios-arrow-down" >
<i-Option v-for="option in selArr" :value="option.label+'|'+option.value" :key="option.value" >
<span >{{option.label}}</span>
</i-Option>
</auto-complete>
</div>
</body>
<script type="text/javascript">
window.vm = new Vue({
el: '#app',
data: {
nowLabel: '', //存儲輸入框中顯示的內容
nowSel: undefined, //存儲需要提交給后台的value
lastLabel: '', //存儲上一次輸入的內容
selArr:[], //存儲select下拉框綁定的列表
isSel:false, ////由於選中和輸入內容都會觸發onchange,設置此變量進行區分兩種情況
//存儲頁面的原始列表
prevArr:[
{
value:'n',
label:'NewYork'
},
{
value:'l',
label:'London'
},
{
value:'s',
label:'Sydney'
},
{
value:'o',
label:'Ottawa'
},
{
value:'p',
label:'Paris'
},
{
value: 'c',
label: 'Canberra'
}
]
},
created:function(){
this.selArr = this.prevArr; //頁面初次加載,下拉列表就是原始列表
},
methods: {
filterMethod:function(value,arr) {
var newArr = [];
for(var i=0;i<arr.length;i++){
if(arr[i].label.toUpperCase().indexOf(value.toUpperCase()) !== -1){
//模糊查詢到了,塞入新數組
newArr.push(arr[i]);
}
}
this.selArr = newArr;
},
changeSel:function(){
//更改事件
var that = this;
if(that.isSel){
//如果輸入框的改變是選中內容引發的,就什么也不做,同時重新初始化標識,為了解決選中同一內容兩次引發的bug
that.isSel = false;
return false;
}
var input = that.nowLabel; //獲取輸入框輸入的內容
that.nowSel = input;
that.clearSelCss(that,"test");
//將輸入內容與上一次的輸入內容比對上一次輸入內容,判斷是到初始化列表中查還是從上次查詢結果列表查
if(input == null || input == undefined || input == ""){
//輸入內容是空,顯示原始列表
that.selArr = that.prevArr;
}else if(input.indexOf(that.lastLabel)==0){
//此次輸入內容是上次輸入內容的開頭,不需要到原始列表查,只要到上次查詢結果中查
that.filterMethod(input,that.selArr);
}else{
//其他情況到原始列表中查
that.filterMethod(input,that.prevArr);
}
this.lastLabel = input;
},
selectSel:function(val){
let that = this;
//選中事件
that.isSel = true;
var label = val.split("|")[0];
that.nowSel = val.split("|")[1];
Vue.nextTick(function () {
that.nowLabel = label;
that.clearSelCss(that,"test");
var focusItem = $(that.$refs.test.$el).find(".ivu-select-item-focus");
//定義一個屬性,用於給選中項設置樣式,之所以不設置class,是因為iview會將class替換掉
focusItem.attr("myfocus","myfocus");
});
},
clearSelCss:function(that,ref){
//清除掉已經被選中的項的css
var lastSel = $(that.$refs[ref].$el).find("[myfocus]");
lastSel.removeAttr("myfocus");
}
}
})
</script>
</html>
效果如下,當選中了列表中的內容的時候,需要提交給后台的是選中項的value,而不是label

當自己輸入內容的時候,由於並不確定value的值,就認為輸入框中的內容就是value,效果如下:

如果有什么疑問,歡迎留言!
