vue實現下拉框全選和輸入匹配


實際項目中的一個需求:

點擊文本框,彈出帶有復選框的選項,然后獲取選中項的數據,傳給后面的一個功能。在文本框輸入內容,也會動態的匹配下拉列表,並且列表帶有全選功能。

 

朴素的效果圖:

 

 

我選擇了用vue實現,算是vue的一次練手吧。不會寫的地方也百度了一下。

難點有兩個,一個是全選。全選不光是點擊全選復選框,選項跟着選中或不選中。還包括反向的選擇,就是如果把所有選項選中了,那么“全選”也要跟着選中,而有任何一項未選中,那么“全選”則處於未選中狀態。也就是說這是個互動的過程。只有做到這點,才是一個好的用戶體驗。

我是在循環數據的每一項加了一個表示選中狀態的值lineCheck。全選和選項的點擊分別寫。點擊全選中,把選項的狀態置為和其一致就可以。

點擊選項時,利用every方法,只有每一項為真(也就是選中),全選才為真,否則為假(未選中)。 

第二個難點就是輸入時的匹配問題,是在computed中寫了一個searchLists,下拉列表的for循環也用的這個數據,全選時遍歷的也是這個數據。

 

其他tips:

1)表單的操作離不開v-model

2)點擊事件加上stop修飾符,阻止冒泡

3)復選框的事件用的change

4)注意用label,這樣點擊文字也有效果,體驗更佳

5)點擊頁面空白處,隱藏下拉列表

 

總體來說,用戶體驗做的還是不錯的。

貼出完整代碼:(沒有好看的樣式,就是最朴素的效果,畢竟css對於前端人員來說是最最簡單的)

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>下拉框全選</title>
        <link rel="stylesheet" href="css/this.css" />
    </head>
    <body>
        <div class="m-select-wrap" id="v_app">
            <div class="title">
                <input type="text" placeholder="輸入/勾選" v-model="searchLine" @click.stop="showList" @focus="inputFocus">
                <span class="show-list" @click.stop="toggleList"></span>
                <span class="select-con">選中了:{{selectCon}}</span>
            </div>
            <ul v-if="isShow" @click.stop="showList">
                <li>
                    <label><input type="checkbox" v-model="checkAllState" @change="checkAll"> 全選</label>
                </li>
                <li v-for="item in searchLists">
                    <label :id="item.lineId"><input type="checkbox" v-model="item.lineCheck" @change="checkOne(item)"> {{item.lineName}}</label>
                </li>
            </ul>
        </div>

        <script src="js/vue.js"></script>
        <script>
            var lines = [
                {
                    lineId: 'line1',
                    lineName: '數據1',
                    lineCheck: false
                },
                {
                    lineId: 'line2',
                    lineName: '數據2',
                    lineCheck: false
                },
                {
                    lineId: 'line3',
                    lineName: '數據3',
                    lineCheck: false
                },
                {
                    lineId: 'line4',
                    lineName: '數據4',
                    lineCheck: false
                },
                {
                    lineId: 'line5',
                    lineName: '數據5',
                    lineCheck: false
                }                
            ]

            new Vue({
                el: '#v_app',
                data: {
                    //數據
                    lineList: lines,
                    //選項的選中狀態
                    checkAllState: false,
                    //選中的數據
                    checkedList: [],
                    //文本框的值
                    searchLine: '',
                    //下拉列表是否顯示
                    isShow:false,
                    //選中的內容
                    selectCon:''
                },
                methods: {
                    //全選
                    checkAll: function() {
                        for (var i = 0; i < this.searchLists.length; i++) {
                            this.searchLists[i].lineCheck = this.checkAllState;
                        }                        
                        this.getCheckData();
                    },
                    //選擇單個
                    checkOne: function(item) {
                        this.searchLists.every(function(item) {
                            return item.lineCheck == true;
                        }) ? this.checkAllState = true : this.checkAllState = false;                        
                        this.getCheckData();                        
                    },
                    //獲取選中的數據
                    getCheckData: function() {
                        this.checkedList = this.searchLists.filter(function(item) {
                            return item.lineCheck == true;
                        })
                        
                        //選中的值顯示到輸入框中
                        this.selectCon='';
                        for(var i=0;i<this.checkedList.length;i++){
                            this.selectCon+=this.checkedList[i].lineName+',';
                        }                
                    },
                    //切換下拉列表
                    toggleList:function(){
                        this.isShow=!this.isShow;                        
                    },
                    //顯示下拉列表
                    showList:function(){
                        this.isShow=true;                        
                    },
                    //文本框獲得焦點時文字被選中
                    inputFocus:function(e){
                        e.currentTarget.select();
                    }                    
                },
                computed: {
                    //輸入框篩選列表
                    searchLists: function() {
                        var _search = this.searchLine;
                        if (_search) {
                            return this.lineList.filter(function(item) {
                                return Object.keys(item).some(function(key) {
                                    return String(item.lineName).toLowerCase().indexOf(_search) > -1
                                })
                            })
                        }
                        return this.lineList;
                    }
                },                
                mounted:function(){
                    var _this=this;
                    //點擊頁面空白處隱藏下拉列表
                    document.addEventListener('click',function(){                        
                        _this.isShow=false;
                    });
                }
            });
        </script>
    </body>
</html>

 

css:

.m-select-wrap{width: 300px;margin: 20px auto 0;}
.m-select-wrap .title{width: 300px;position: relative;}
.m-select-wrap input[type="text"]{width: 300px;height: 40px;padding: 0 5px;}
.m-select-wrap .select-con{position: absolute;left: 105%;white-space: nowrap;line-height: 40px;}
.m-select-wrap .show-list{position: absolute; width: 30px;height: 40px;line-height: 38px;border: 1px solid #aaa;right: 0;text-align: center;cursor: pointer;}
.m-select-wrap ul{border: 1px solid #ccc;padding:0 30px 10px 10px;}
.m-select-wrap li{margin-top: 10px;}


免責聲明!

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



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