Vue 自動補全外掛
阿新 • • 發佈:2018-12-27
Vue實現的輸入框自動補全外掛:
先說實現的效果:
不想廢話,主要用到了以下的幾點:
1.子元件需要通過父元件輸入的關鍵字從後端做智慧匹配,這裡使用
props:父元件向子元件傳遞引數
$parent.$data:子元件對父元件的引數進行賦值
目的:父子元件通訊
2.CSS切換效果,這裡主要對生成的下拉列表中的列舉進行選擇時,頁面的動畫效果
3.為了保證點選螢幕中其他位置,使頁面彈出的智慧提示下拉列表消失。這裡使用blur事件,不過控制元件中同時使用了click事件,為了保證點中下拉列表中的每項的click事件不被輸入框的blur事件覆蓋,這裡給blur事件中新增settimeout方法,以保證click事件能夠正常執行!
4.網路傳輸使用非同步,不過這裡使用原生的XMLHttpRequest來進行通訊,而不使用vue-resource,目的是儘可能的脫離對其他vue的庫的依賴
<style> .transition, .autocomplete, .showAll-transition, .autocomplete ul, .autocomplete ul li a{ transition:all 0.3s ease-out; -moz-transition:all 0.3s ease-out; -webkit-transition:all 0.3s ease-out; -o-transition:all 0.3s ease-out; } .autocomplete ul{ font-family: sans-serif; position: absolute; list-style: none; background: #f8f8f8; margin: 0; display: inline-block; min-width: 15%; margin-top: 10px; } .autocomplete ul:before{ content: ""; display: block; position: absolute; height: 0; width: 0; border: 10px solid transparent; border-bottom: 10px solid #f8f8f8; top: -20px } .autocomplete ul li a{ text-decoration: none; display: block; background: #f8f8f8; color: #2b2b2b; padding: 5px; } .autocomplete ul li a:hover, .autocomplete ul li.focus-list a{ color: white; background: #2F9AF7; } .showAll-transition{ opacity: 1; height: 50px; overflow: hidden; } .showAll-enter{ opacity: 0.3; height: 0; } .showAll-leave{ display: none; } .autocomplete-person{ margin-left: 7px; } </style> <template> <input type="text" :id="id" :class="class" :name="name" :placeholder="placeholder" v-model="inputmodel" @input="input(inputmodel)" @blur="hideAll" @keydown="keydown" @focus="focus" /> <div class="autocomplete transition autocomplete-{{ name }}" id="autocomplete-{{ name }}" v-show="showList"> <ul> <li v-for="data in json" transition="showAll" :class="activeClass($index)"> <a href="#" @click.prevent="$emit('selectList',data)" @mousemove="mousemove($index)"> <b>{{ data[anchor] }}</b> </a> </li> </ul> </div> </template> <script> import Vue from 'vue' //轉場效果 Vue.transition('showAll',{}); export default { props: { id: String, class: String, name: String, placeholder: String, //父元件模型名稱 model: String, //JSON資料取值的Key anchor: { type: String, required: true }, //請求的資料鏈接 url: { type: String, required: true }, //請求的引數KEY param: { type: String, default: 'q' }, //拉取的資料個數的限制 limit: { type: String, default: 5 } }, data:function(){ return { showList: false, inputmodel:'', json: [], focusList: '' } }, methods: { //轉化JSON物件 cleanUp:function(data){ return JSON.parse(JSON.stringify(data)); }, input:function(val){ this.showList = true; //觸發呼叫getData方法 this.$emit('getData',val); }, //隱藏補全列表 hideAll:function(e){ //為了讓blur方法延遲執行,以便能夠成功執行click方法 setTimeout(() => { this.showList = false; },250); }, // focus:function(e){ this.focusList = 0; }, mousemove:function(i){ this.focusList = i; }, //鍵盤移動 keydown:function(e){ let key = e.keyCode; //如果沒有展示的list,則直接返回 if(!this.showList) return; switch (key) { case 40: //向上 this.focusList++; break; case 38: //向下 this.focusList--; break; case 13: //確認 this.$emit('selectList', this.json[this.focusList]); this.showList = false; break; case 27: //退出 this.showList = false; break; } //點中的序號超過陣列的長度時,迴圈到第一個 let listLength = this.json.length - 1; this.focusList = this.focusList > listLength ? 0 : this.focusList < 0 ? listLength : this.focusList; }, //更新樣式 activeClass:function(i){ return { 'focus-list' : i == this.focusList }; } }, events: { //選中列表中的哪一項 selectList:function(data){ console.log(JSON.stringify(data)); let clean = this.cleanUp(data); //按照指定的JSON鍵值顯示在模型上 this.inputmodel = clean[this.anchor]; //傳遞給父元件中的物件 this.$parent.$parent.$data[this.model] = clean; this.showList = false; }, //獲取資料 getData:function(val){ let self = this; if(this.url != null){ let ajax = new XMLHttpRequest(); var limit; if(this.$get('limit') != ''){ this.limit = parseFloat(this.limit); limit = this.limit != "" ? '&limit=' + this.limit : ''; }else{ limit = ''; } ajax.open('GET', `${this.url}?${this.param}=${val}${limit}`, true); ajax.send(); ajax.addEventListener('progress', function (data) { if(data.lengthComputable){} }); ajax.addEventListener('loadend', function (data) { let json = JSON.parse(this.responseText); self.json = json; }); } } }, created:function(){ //同步從父元件傳遞過來的值 this.inputmodel = this.$parent.$data[this.model].staffChnName; } } </script>
呼叫方式:
元件還沒有做的足夠獨立和靈活,筆者也會盡可能的改善,如果有問題的話,希望大家留言我的郵箱
程式設計師惜程式設計師,不喜勿噴,心累~