vue防抖动,vue 节流
本文主要介绍vue防抖和节流的相关资料,帮助大家更好的了解和学习VUE框架,感兴趣的朋友可以了解一下。
什么是防抖节流?
函数防抖(debounce)
说明:当一个事件被连续触发时,如果在一定时间间隔内没有事件被再次触发,事件处理函数将只执行一次。如果事件在设定的时间间隔到来之前再次触发,延迟将再次开始。
情况:连续触发滚动事件时,不会立即执行handle函数。当1000毫秒内没有触发scroll事件时,handle函数会延迟一次。
功能去抖(fn,等待){
让超时=空
返回函数(){
如果(超时!==null) clearTimeout(超时)
timeout=setTimeout(fn,wait);
}
}
函数句柄(){
console.log(Math.random())
}
window . addevent listener( scroll ,debounce(handle,1000))
addEventListener的第二个参数实际上是去抖函数中的返回方法。let timeout=null只有在addEventListener期间执行一次触发事件时,这行代码才会被执行,所以每次触发scroll事件时,最后一个延迟会被清除,并记录一个新的延迟。当滚动事件停止触发时,最后记录的延迟将不会被清除,并且可以被延迟。这就是去抖功能的原理。
函数节流(throttle)
说明:当事件被连续触发时,事件处理函数会定期执行。
案例:连续触发scroll事件时,handle函数不是立即执行,而是每隔1000毫秒才执行一次。
功能油门(fn,延迟){
var prev=Date.now()
返回函数(){
var now=Date.now()
if(当前-先前延迟){
fn()
prev=Date.now()
}
}
}
函数句柄(){
console.log(Math.random())
}
window . addevent listener( scroll ,throttle(handle,1000))
类似于防抖的原理,每次执行fn函数,都会更新prev来记录这次执行的时间。当下一个事件被触发时,会判断时间间隔是否达到预设的设置,重复上述操作。
防抖和节流都可以用于鼠标移动、滚动、调整大小、输入和其他事件。它们的区别在于,防抖将仅在连续事件周期结束时执行一次,而节流将在事件周期中以一定间隔定期执行几次。
Vue中实践
vue实现防抖只有以下两种方式。
封装实用工具
包装组件
封装utils工具
通过修改上面的例子,可以封装一个简单的utils工具。
实用工具
让超时=空
功能去抖(fn,等待){
如果(超时!==null) clearTimeout(超时)
超时=设置超时(fn,等待)
}
导出默认去抖
app.js
输入类型= text @ input= de bounce input($ event)
从导入去抖。/utils
导出默认值{
方法:{
去抖输入(E){
去抖(()={
console.log(E.target.value)
}, 1000)
}
}
}
封装组件
至于组件的封装,需要用到属性$listeners和$attrs,这两个都是vue2.4的新内容,官网的介绍比较晦涩。让我们看看他们是怎么做的:
$listeners:父组件绑定子组件时,会在子组件上绑定很多属性,然后通过props在子组件中注册使用,所以没有被props注册的会放在$listeners中,当然不包括class和style,可以通过v-bind="$ attrs "传入子组件的内部组件。
$listeners:由父组件绑定到子组件上的事件,但没有。原生修饰符将放在$listeners中,可以通过v-on="$ listeners "传入内部组件。
简单来说,$listeners和$attrs是属性和事件的继承,对于组件的二次封装非常有用。
我们以element-ui的el-input组件为例,封装了一个带防抖的去抖输入组件。
去抖-输入. vue
模板
输入v-bind= $ attrs @ input= de bounce input /
/模板
脚本
导出默认值{
data() {
返回{
超时:空
}
},
方法:{
去抖输入(值){
如果(this.timeout!==null)clear time out(this . time out)
this.timeout=setTimeout(()={
这个。$emit(输入,值)
}, 1000)
}
}
}
/脚本
app.vue
模板
去抖-输入占位符=防抖前缀-icon= El-icon-search @ input= input eve /去抖-输入
/模板
脚本
从导入去抖输入。/去抖-输入
导出默认值{
方法:{
输入值{
console.log(值)
}
},
组件:{
去抖输入
}
}
/脚本
以上组件用$attrs封装。虽然开发者不需要关注属性的传递,但是使用起来还是不太方便,因为样式的限制就是把输入封装在里面。接触过react高层组件的同学可能知道,react高层组件本质上就是一个React组件,其功能传入包中。经过一系列过程,最终返回一个相对增强的React组件。那么我们可以借鉴vue的这个思路吗?我们来看看vue的功能组件。
函数式组件
什么是功能组件?
功能组件是指用一个函数渲染一个vue组件,这个函数只接受一些道具。我们可以将这种组件标记为功能性的,这意味着它没有状态(没有响应数据)和实例(没有上下文)。
功能组件看起来像这样:
导出默认值()={
功能性:真的,
道具:{
//Props是可选的。
},
//为了弥补缺少的实例,请提供第二个参数作为上下文
render: function (createElement,context) {
返回vNode
}
}
注意:在2.3.0之前的版本中,如果一个功能组件想要接收prop,prop选项是必需的。在2.3.0或更高版本中,可以省略prop选项,所有组件上的特征将自动隐式解析为prop。但是一旦你注册了道具,只有注册的道具才会出现在context.prop中
使用render函数的第二个参数context,而不是context this。它是一个具有以下字段的对象:
道具:提供所有道具的物品。
Children: VNode子节点的VNode数组。
Slots:返回包含所有插槽的对象的函数。
ScopedSlots: (2.6.0)公开传入作用域插槽的对象。公共槽也被公开为一个函数。
Data:传递给组件的整个数据对象,作为createElement的第二个参数传入组件。
父组件:对父组件的引用。
Listeners: (2.3.0)包含由当前组件的父组件注册的所有事件侦听器的对象。这是data.on的别名
注入:(2.3.0)如果使用注入选项,对象包含应该注入的属性。
vm.$slots API 里面是什么
槽用于访问由槽分发的内容。每个命名槽都有自己的属性(例如,v-slots: foo的内容将在v-slot:foo中找到)。默认属性包括所有未包含在命名槽中的节点,或v-slot:default的内容。
slots() 和 children 对比
你可能想知道为什么同时需要slots()和children。不是插槽()。默认类似儿童?在某些场景下是——,但是如果是下面这个有子节点的功能组件呢?
我的功能组件
p v型槽:foo
第一
/p
p秒/p
/我的功能组件
对于这个组件,孩子会给你两个段落标签,而slots()。默认只会传递第二个匿名段落标签,和slots()。foo将传递第一个命名的段落标签。同时拥有children和slots(),那么可以选择让组件感知一个slot机制,或者简单的传递children,交给其他组件处理。
一个函数式组件的使用场景
假设有一个组件A,它引入了三个组件A1、A2和A3。组件A的父组件向组件A发送type属性,组件A根据type的值决定显示A1、A2、A3中的哪一个组件。在这个场景中使用功能组件非常方便。那么为什么要使用功能组件呢?底线:渲染开销低,因为功能组件只是功能。
用函数式组件的方式来实现防抖
因为业务关系该防抖组件的封装同时支持输入、按钮、el输入、el按钮的使用,如果是投入类组件对投入事件做防抖处理,如果是按钮类组件对点击事件做防抖处理。
常数去抖=(fun,delay=500,之前)={
让定时器=空
return (params)={
计时器窗口. clearTimeout(计时器)
之前之前(参数)
timer=window.setTimeout(()={
//点击事件乐趣是功能输入事件乐趣是排列
如果(!Array.isArray(fun)) {
好玩=[好玩]
}
为了(让我开心){
乐趣[我]参数)
}
计时器=空
},parseInt(delay))
}
}
导出默认值{
名称:去抖,
功能性:真,//静态组件当不声明功能的时该组件同样拥有上下文以及生命周期函数
render(createElement,context) {
const before=上下文道具。以前
常量时间=context.props.time
const vnodeList=context.slots().系统默认值
if (vnodeList===undefined){
console.warn(去抖组件必须要有子元素)
返回空
}
const vnode=vnodeList[0] null//获取子元素虚拟数字正射影像图
if (vnode.tag===input) {
const默认fun=vnode。数据。开着。投入
const de bounce fun=de bounce(默认fun,时间,之前)//获取节流函数
vnode.data.on.input=去抖音
} else if (vnode.tag===button) {
const默认fun=vnode。数据。开着。点击
const de bounce fun=de bounce(默认fun,时间,之前)//获取节流函数
vnode。数据。开着。点击=de弹跳乐趣
} else if(vnode。元件选项vnode。组件选项。tag=== El-input ){
const默认fun=vnode。组件选项。听众。投入
const de bounce fun=de bounce(默认fun,时间,之前)//获取节流函数
vnode。组件选项。听众。输入=de bounce fun
} else if(vnode。元件选项vnode。组件选项。tag=== El-button ){
const默认fun=vnode。组件选项。听众。点击
const de bounce fun=de bounce(默认fun,时间,之前)//获取节流函数
vnode。组件选项。听众。点击=de弹跳乐趣
}否则{
console.warn(去抖组件内只能出现下面组件的任意一个且唯一埃尔按钮、el输入、按钮、输入)
返回虚拟节点
}
返回虚拟节点
}
}
原理也很简单就是在虚拟节点中拦截在下面的点击、输入事件做防抖处理,这样在使用上就非常简单了。
自定义指令 directive
我们来思考一个问题,函数式组件封装防抖的关节是获取vNode,那么我们通过自定义指令同样可以拿到vNode,甚至还可以得到原生的多姆,这样用自定义指令来处理会更加方便。
自定义指令:https://cn。vue js。org/v2/guide/custom-directive超文本标记语言
主页。射流研究…
Vue.directive(dinput ,{
bind: function(el,binding,vnode) {
设超时=空
el.addEventListener(input ,function() {
如果(超时!==null) clearTimeout(超时);
timeout=setTimeout(function() {
vnode。上下文[绑定。表达式]();
}, 1000);
});
}
});
某视频剪辑软件
输入类型=text v-dinput=myfunc/
射流研究…
导出默认值{
名称:"应用程序",
数据:函数(){
返回{
登录用户:空
};
},
方法:{
myfunc() {
控制台。信息(“我的功能”);
}
}
}
这种方式的缺点
调用方法时无法传参
以上就是浅析VUE防抖与节流的详细内容,更多关于VUE防抖与节流的资料请关注我们其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。