上一篇讲到了 JavaScript 的节流函数和防抖函数, 那么我们在实际场合中该如何运用呢?
首先, 我们来理解一下: 节流函数首先是节流, 就是节约流量, 内存的损耗, 旨在提升性能, 在高频率频发的事件中才会用到, 比如: onresize,onmousemove,onscroll,oninput 等事件中会用到节流函数;
输入框的模糊查询功能原理分析
所谓模糊查询就是不需要用户完整的输入或者说全部输入信息即可提供查询服务, 也就是用户可以在边输入的同时边看到提示的信息 (其实是查询出来匹配到的信息), 百度的搜索功能就是很好的模糊查询的例子; 其实模糊查询的原理就是给输入框绑定 oninput 事件监听用户输入情况, 然后每次用户只要在输入框中输入了信息就触发事件进行查询然后实时展示; 原理很简单, 但是实现起来会有一些问题, 我们可以想想, 每输入一个字符都会触发事件, 那如果我们需要输入很长的信息呢, 那查询是不是就得触发多次? Ajax 连续多次触发, 再加上如果我们的方法体中有操作 DOM 元素的方法, 那么必然会给我们的浏览器进入假死甚至崩溃状态; 那么我们有没有办法来解决此类问题呢? 答案是: 有的;(不了解模糊查询功能的同学可以出门右转去百度首页试一下搜索, 给你 5 分钟, 我等你回来)
html 视图层代码:
- <div id="app">
- // 输入框, 绑定输入框的值是变量 input_value 的值, 然后对输入框做了事件绑定 keyup, 在用户输入的时候会触发
- <input type="text" placehold="请输入 id 进行查询" v-model="input_value" @keyup="throttle" ref="input"/>
- <ul v-show="state">
- <li v-for="(item,index) in list" :key="index">
- <span>{{item.id}}</span>
- <span>{{item.name}}</span>
- <span>{{item.time}}</span>
- </li>
- </ul>
- </div>
从上述代码中我们可以很明显的看到 DOM 结构, 就是一个输入框, 我们给输入框加了 ref 属性是为了方便我们后面操作 DOM 拿到输入框的值 (详情可见 ref 和 $refs 的区别博文 https://www.cnblogs.com/dengyao-blogs/p/11350292.html), 然后下面有一个 ul 列表, 不过 ul 列表是判断展示的;(至于为什么会用 v-show 而不是 v-if, 可以点击链接查阅之前的博文 https://www.cnblogs.com/dengyao-blogs/p/11378228.html);
JS 数据逻辑层代码:
- // 实例化 vue 对象
- new Vue({
- el:"#app",
- data:{
- input_value:"",
- state:false,
- statu:true,
- dataList:[
- { id: "1001", name: "哈哈", time: "20170207" },
- { id: "1002", name: "呵呵", time: "20170213" },
- { id: "1103", name: "晓丽", time: "20170304" },
- { id: "1104", name: "小兰", time: "20170112" },
- { id: "1205", name: "财务", time: "20170203" },
- { id: "1206", name: "嘻嘻", time: "20170208" },
- { id: "1307", name: "测试", time: "20170201" }
- ],
- list:[]
- },
- methods:{// 触发 keyup 事件之后触发的方法
- search(){
- // 这个变量主要是用来测试节流后和不节流的区别
- var i=0;
- console.log(i++);
- // 定义的新数组存放筛选之后的数据
- this.list=[];
- // 拿到当前 input 输入框输入的值
- this.input_value=this.$refs.input.value;
- // 判断展示 ul 列表, 如果输入了就展示没输入就不展示
- if(this.input_value.length>0){
- this.state=true;
- }else{
- this.state=false;
- }
- // 循环模拟数据的数组
- this.dataList.map((msg)=>{
- // 拿当前 JSON 的 id,name,time 去分别跟输入的值进行比较
- //indexOf 如果在检索的字符串中没有出现要找的值是会返回 - 1 的, 所以我们这里不等于 - 1 就是假设输入框的值在当前 JSON 里面找到的情况
- if(msg.id.indexOf(this.input_value)!=-1 || msg.name.indexOf(this.input_value)!=-1 || msg.time.indexOf(this.input_value)!=-1){
- // 然后把当前 JSON 添加到 list 数组中
- this.list.push(msg);
- }
- })
- },
- }
- })
JS 数据逻辑层代码其实不难, 主要就是给 input 绑定了 keyup 事件, 在用户输入的时候会触发 search 事件, 用户每输入一个字符都会触发一次; 然后我们通过 this.$refs.input.value 来获取输入框当前的值并赋值给变量 this.input_value, 然后我们对 this.input_value 的长度进行判断来实现对用户是否输入的判断, 如果用户输入了我们就把 v-show 绑定的值 state 赋值给 true, 反之则赋值为 false; 然后我们来用 ES6 的 map 方法来循环我们的 dataList 数组, dataList 数组的数据是模拟后台接口数据, 通过 indexOf 方法是否等于 - 1 来进行判断当前 JSON 里面是否有输入框中输入的数组, indexOf 是 JavaScript 提供的操作字符串方法, 调用方式: string.indexOf("要查询的值"), 如果 str 中没有要查询的值会返回我们 - 1, 如果有会直接返回给我们查询数据的当前下标; 所以我们可以借助 indexOf 是否等于 - 1 来进行判断当前 JSON 中是否有我们要查询的字符串; 如果有的话, 我们只需要把当前 JSON 添加到空数组 list 中即可, 然后 li 绑定 list 展示;
效果图如下:
image
到这里我们就可以看到我们要的模糊查询功能已经实现了, 但是我们上面讲到模糊查询会影响浏览器的性能, 从控制台输入的变量 i 的值可以看到我们的 search 方法已经被调用了 8 次, 我们输入的字符越长被调用的次数越多, 如果方法里面有操作 DOM 的行为性能影响会更严重; 所以我们现在来加上节流函数来看看:
- // 节流函数
- throttle(){
- // 保持 this 的指向始终指向 vue 实例
- var that=this;
- if(!that.statu){
- return;
- }
- that.statu=false;
- setTimeout(function(){
- console.log(new Date());
- that.search();
- that.statu=true;
- },1000)
- },
我们把我们写的节流函数封装在 throttle 里面执行, 把 @keyup 绑定的点击事件修改为 throttle, 当用户输入字符的时候触发节流函数; 效果图如下:
image
我们可以从控制台很清晰的看到当我们使用节流函数的时候, 当我们输入了 8 个字符我们的方法只执行了两次, 并且执行时间是每隔一秒执行一次, 一个方法执行 2 次肯定会比执行 8 次不管是在效率还是在性能方面都会是比较大的提升, 用了节流函数之后相对上面没用的节流函数来说, 我们极大的实现了性能提升, 优化, 所以在高频率触发的事件中我们是可以建议用节流函数来进行控制和解决问题的;
来源: http://www.jianshu.com/p/6f0dfd7cfeee