Vue 自动补全插件
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>
调用方式:
组件还没有做的足够独立和灵活,笔者也会尽可能的改善,如果有问题的话,希望大家留言我的邮箱
kameleon@126.com
程序员惜程序员,不喜勿喷,心累~
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: 为 Vue 编写一个插件
- 下一篇: PHP连接MySQL数据库及以表格输出数据库数据的实现