js中防抖函数debounce及父子周期执行顺序的应用

10 篇文章 0 订阅
9 篇文章 0 订阅

js中防抖函数debounce()

在开发网站时,我们有时候需要一直监听某些事件,事件触发就访问后台,请求数据,但是我们知道,如果手机端的网页是当我们每次请求的都是大量数据时,需要刷新一下页面长度,才能有效的使用better-scroll,但是过于频繁的刷新也会影响效率,比如,在手机上看某些商城的时候,一直往下滑会一直有数据请求,也会一直刷新页面长度

但是每请求一次图片就刷新一次长度会导致过于频繁,如果每请求

<img :src="goodsItem.show.img" alt="" @load="imageLoad">

当图片加载完时,触发imageLoad操作

  methods: {
    imageLoad() {
      this.$bus.$emit('itemImageLoad')
      有人会问这里为什么要用$bus去发射函数?因为在这个项目中,图片所在组件goodsListItem中,调用图片组件的是goodslist组件,而调用goodslist组件和监听事件发生的组件在home.vue中,而真正执行刷新操作的scroll是在scroll组件中,所以通过父子传递信息过于繁杂,所以干脆设置一个bus总线,监听事件并传递消息
    },
  },

imageLoad函数中,emit函数,就是发出函数,发出itemImageLoad事件

Vue.prototype.$bus = new Vue()

而这个$bus早已在Vue的原型中定义好了,所以可以调用emit函数

this.$bus.$on('itemImageLoad',() => {
      // this.$refs.scroll && this.$refs.scroll.refresh()
      refresh()
    })

发出后,在home这边进行监听,触发事件,执行refresh(),也就是刷新图片的高度,有人会问,既然要一组图片请求一次,那么为什么不在请求完成后刷新一次高度呢?其实,我们要做的防抖动,就是要用这样的思想,但是如果你想的是,一请求就立马刷新高度,就不可行,为什么?因为你请求了一组图片,但是数据是一张一张的获取,或者说一个字符一个字符的获取,所以实际高度也是一点一点的变,如果你在请求数据后立马刷新高度,你的better-scroll高度可以说是不变的,运气好会变长一点点,但是图片会接踵而至,实际高度不断增加,所以我们最好,每来一张图片就刷新一次better-scroll的高度,
但是这样刷新又太频繁了,我们能不能刚好在它请求完一组数据后才刷新呢?能不能在它网速不好的时候,一组数据请求的很慢,中途卡住的时候,就刷新高度?好让其可以访问已经请求好的图片呢?
没错,这里就要用到我们的debounce()防抖动处理

父子组件周期执行顺序

这个代码其实挺有意思的,首先执行了debounce函数,
然后将其中的匿名函数返回,赋值给refresh,但是这个时候是没有执行其中的匿名函数的,因为你只是返回了,而且refresh也不带括号,所以只是一个函数变量。而真正执行是在触发itemImageLad后执行refresh的

至于为什么这个代码要放在mounted中而不是created中,可以查看我上一篇文章,因为如果放在created中,很有可能会出现找不到子组件scroll等相关undefined错误,因为父组件是最先created的,而mounted缺要等到子组件mounted之后才行
mounted:{
	const refresh = this.debounce(this.$refs.scroll.refresh, 200)
	    this.$bus.$on('itemImageLoad',() => {
	      // this.$refs.scroll && this.$refs.scroll.refresh()
	      refresh()
	    })
 }
//真正的刷新高度函数其实是在this.$refs.scroll.refresh中调用的,我们将debounce函数中的返回函数赋值给refresh,然后当触发itemImageLoad的时候就调用refresh
    

debounce(func, delay) {
      let timer = null
      return function (...args) {
        if (timer) clearTimeout(timer)

        timer = setTimeout(() => {
          func.apply(this,args)
        },delay)
      }
    },

在debounce中,设置了一个定时器,在0.2s后执行,最开始的timer设置为null,加入,第一张图片加载完成后执行debounce函数,空定时器,所以设置一个定时器,在0.2s后执行func,也就是scroll.refresh(),如果在0.2之内,第二张图片也加载完成,继续触发refresh也就是debounce中的返回的匿名函数,而timer是存在的,我们就clearTimeout,再继续设置一个timer,同样,如果还在0.2s完成了第三张图片的加载,就继续清除定时器然后再设置一个新的定时器。
以上就是防抖函数的实际应用,当然我还有个问题,就是为什么timer在一次又一次被refresh重新操作的时候,会留存下来?按道理,执行第二次refresh的时候,timer应该已经没了,因为第一次refresh是第一次的refresh,第二次是第二次的,所以有点不太明白,除非说let的作用域是块级作用域,所以导致了,timer是一直存在于refresh中的。我只能这么自己解释。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值