vue怎么编写规则(vue使用节流函数的踩坑实例指南)
类别:编程学习 浏览量:1989
时间:2022-01-27 01:12:06 vue怎么编写规则
vue使用节流函数的踩坑实例指南前言
一个常见的业务场景,我们要在input搜索框输入结束后,发送相关请求,获取搜索数据。频繁的事件触发会导致接口请求过于频繁。所以需要我们对此加以限制,来禁止不必要的请求,以免资源的浪费~
举一个🌰 业务场景
概念:
关于防抖函数的介绍
关于addEventListener
使用示例:
function debounce(fn) { let timeout = null; // 创建一个标记用来存放定时器的返回值 return function () { clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉 timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 // interval 间隔内如果还有字符输入的话,就不会执行 fn 函数 fn.apply(this, arguments); }, 500); }; } function sayHi() { console.log('防抖成功'); } var inp = document.getElementById('inp'); inp.addEventListener('input', debounce(sayHi)); // 防抖
在vue中使用?
首先说一下之前的踩坑行为
下面的代码为简易版的一个场景
function debounce(fn) { let timeout = null; // 创建一个标记用来存放定时器的返回值 return function () { clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉 timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 // interval 间隔内如果还有字符输入的话,就不会执行 fn 函数 fn.apply(this, arguments); }, 500); }; }
错误的使用方式
<template> <li class="search-view"> <li class="header"> <Search class="search-box" v-model='searchValue' @input='getSearchResult' placeholder='搜索想要的好物' /> <span @click="goBack" class="cancel">取消</span> </li> <li class="serach-view-content" /> </li> </template> <script> import Search from './components/Search'; import debounce from './config'; export default { name: 'SearchView', components: { Search }, data() { return { searchValue: '' }; }, methods: { getSearchResult() { debounce(function() { console.log(this.searchValue); })(); } } }; </script>
为什么错误?
源码层级分析
vue模板编译 的解析事件
export const onRE = /^@|^v-on:/ export const dirRE = /^v-|^@|^:/ function processAttrs (el) { const list = el.attrsList let i, l, name, value, modifiers for (i = 0, l = list.length; i < l; i++) { name = list[i].name value = list[i].value if (dirRE.test(name)) { // 解析修饰符 modifiers = parseModifiers(name) if (modifiers) { name = name.replace(modifierRE, '') } if (onRE.test(name)) { // v-on name = name.replace(onRE, '') addHandler(el, name, value, modifiers, false, warn) } } } }
总结: 实例初始化阶段调用的初始化事件函数initEvents实际上初始化的是父组件在模板中使用v-on或@注册的监听子组件内触发的事件
vue的事件机制
Vue.prototype.$on = function(event, fn) { const vm = this; if (Array.isArray(event)) { for (let i = 0; i < event.length; i++) { this.$on(event[i], fn); } } else { //这个_events属性就是用来作为当前实例的事件中心,所有绑定在这个实例上的事件都会存储在事件中心_events属性中。 (vm._events[event] || (vm._events[event] = [])).push(fn); } return vm; }; Vue.prototype.$emit = function(event) { const vm = this; let cbs = vm._events[event]; if (cbs) { cbs = cbs.length > 1 ? toArray(cbs) : cbs; let args = toArray(arguments, 1); for (let i = 0; i < cbs.length; i++) { try { cbs[i].apply(vm, args); } catch (e) { handleError(e, vm, `event handler for "${event}"`); } } } return vm; };
vue的initState中 调用了initMethods方法
initMethods中挂在methods方法到this上
for (const key in methods) { if (process.env.NODE_ENV !== 'production') { if (methods[key] == null) { warn( `Method "${key}" has an undefined value in the component definition. ` + `Did you reference the function correctly?`, vm ); } // 如果和props中某个属性名重名了 抛出异常 if (props && hasOwn(props, key)) { warn(`Method "${key}" has already been defined as a prop.`, vm); } /* 如果methods中某个方法名如果在实例vm中已经存在并且方法名是以_或$开头的,就抛出异常: 提示用户方法名命名不规范 */ if (key in vm && isReserved(key)) { warn( `Method "${key}" conflicts with an existing Vue instance method. ` + `Avoid defining component methods that start with _ or $.` ); } // 将method绑定到实例 vm上 这样我们就可以通过this.xxx 来访问了 // 同时如果在vue中 let m1 = this.xxx m1() this也指向vue vm[key] = methods[key] == null ? noop : bind(methods[key], vm); }
划重点:
- 子组件$emit('input事件')
- 父组件接收事件
getSearchResult.apply(this, agrs) <===> apply的调用可以写成下面的形式 this.getSearchResult(args) // 进而变成这种执行 debounce(function() { console.log(this.searchValue); })(); // 这里的debounce 返回了一个函数 于是变成 (function (fn) { clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉 timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 // interval 间隔内如果还有字符输入的话,就不会执行 fn 函数 fn.apply(this, arguments); }, 500); })() // 到这里 其实就变成了匿名函数的自执行 // 由于每次触发input都会返回一个新的匿名函数 生成一个新的函数执行栈 所以防抖失效~
那么应该如何调用
<template> <li class="search-view"> <li class="header"> <Search class="search-box" v-model='searchValue' @input='getSearchResult()' placeholder='搜索想要的好物' /> <span @click="goBack" class="cancel">取消</span> </li> <li class="serach-view-content"> </li> </li> </template> <script> import debounce from 'lodash.debounce'; export default { name: 'SearchView', components: { Search, }, data() { return { searchValue: '', }; }, methods: { getSearchResult: debounce(function () { console.log(this.searchValue); }, 500), }, }; </script>
分析执行过程
getSearchResult().apply(this, args) <===> 忽略参数行为 只关注执行栈 let func = function () { clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉 timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 // interval 间隔内如果还有字符输入的话,就不会执行 fn 函数 fn.apply(this, arguments); }, 500); }; this.func(args) <===>
子组件触发input的行为 返回的始终是一个同一个函数体 防抖成功
类比于文章开始时介绍的addEventListener
总结
到此这篇关于vue使用节流函数踩坑的文章就介绍到这了,更多相关vue节流函数踩坑内容请搜索开心学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持开心学习网!
您可能感兴趣
- vue 单文件组件(vue实现一个单文件组件的完整过程记录)
- vue界面自动生成(Vue中实现3D标签云的详细代码)
- vue和springboot分页开发实现(解决Vue+SpringBoot+Shiro跨域问题)
- vue 表格数据增加修改(vue element实现表格增加删除修改数据)
- vue中的watch属性(vue Watch和Computed的使用总结)
- vue一个组件两种样式(Vue实现动态样式的多种方法汇总)
- vue elementui侧边栏怎么切换页面(Vue + element实现动态显示后台数据到options的操作方法)
- vue实现pc聊天页面(vue实现web在线聊天功能)
- vue 富文本图片上传(vue.js云存储实现图片上传功能)
- vue 访问后台接口(vue轮询请求解决方案的完整实例)
- vue.js开发网站的关键技术(Vue.js项目前端多语言方案的思路与实践)
- vue组件方法里如何修改data(vue项目中使用rem替换px的实现示例)
- vue动态路由实现权限控制(vue2/vue3路由权限管理的方法实例)
- vue2.0自定义指令(vue2实现provide inject传递响应式)
- vue引入axios(vue封装axios的几种方法)
- uniapp使用vue写页面(分析uniapp入门之nvue爬坑记)
- 这8种耐阴植物,营造阴生植物花境,也是一个不错的选择(营造阴生植物花境)
- 览邦G08 Plus SMART WATCH 测评⑱ 全独立这才是智能手表该有的样子(览邦G08PlusSMART)
- 荣耀手表 GS 3 真机亮相 不支持无线充电(荣耀手表GS3)
- 通过体温就能为智能手表充电 原来是用NASA在空间站用的黑科技(通过体温就能为智能手表充电)
- 智能手表兼容Windows和Android 无需充电挑战苹果(智能手表兼容Windows和Android)
- 一天一冲也算表 麦步,一款待机 21 天的智能手表体验评测(一天一冲也算表)
热门推荐
- react的事件绑定(React事件绑定的方式详解)
- 云数据中心服务器介绍(云服务器的机房设备有哪些?)
- dedecms手册教程(dedecms标签大全非常经典)
- 数组reduce方法的好处(JS使用reduce方法处理树形结构数据)
- 云服务器和虚拟空间有什么区别(云服务器、虚拟机是一样的吗?有什么不同?)
- laravel框架的高级知识点(laravel配置Redis多个库的实现方法)
- dedecms路径设置(dedecms V5.7修改表前缀的方法及出现不显示文章内容的解决方法)
- 如何判断数据是json还是字符串(JSON.stringify的多种用法总结)
- laravel自定义使用方法(laravel 修改.htaccess文件 重定向public的解决方法)
- python编写自动发送微信信息(python实现向微信用户发送每日一句 python实现微信聊天机器人)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9