完成iview的下拉select既可以編輯內容又可以選擇下拉選項的功能(借助iview的自動完成組件)


最近在使用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,效果如下:

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM