最近在使用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,效果如下:
如果有什么疑問,歡迎留言!