【Vue项目复习笔记】滚动区域的Bug分析与解决

因为上一次解决的滚动区域bug是依靠第三方里面的东西,现在我们不依靠第三方的东西如何解决呢?

首先:我们先要把项目中的关于加载更多的内容删掉,然后不依靠第三方的东西完成此次功能
此时出现以下情况:
请添加图片描述
我们此时查看一下BScroll里面的scrollerHeight值

在这里插入图片描述
此时这个scrollerHeight的高度是1464,这个高度是不包括图片的高度,因为这在better-scroll中只能滚动1464,但是我们真实的滚动高度远远不止1464,所以这个时候就出现了问题。
在这里插入图片描述
那我们怎么才能让其把这个高度重新计算一次呢?
我们只需要执行一次

this.scroll.refresh()

等把所有的图片加载完成以后执行一次refresh(),一旦我们执行了这个refresh()以后,它内部就会根据我们最新的子组件,我们的GoodlistItem重新计算最新高度。那么问题又来了,我怎么知道我的图片加载完成了?我们必须要将图片加载完成和我们的refresh()对应起来。
我们第一步先要监听图片加载,这个滚动的图片是在我们的GoodsListItem组件中的img中,所以有:

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

在这里插入图片描述
怎么才能将图片加载完成和我们的refresh()对应起来,第一种方法是,将我们的图片加载完成以后执行的this.scroll.refresh()这个事件传给他的父组件GoodsList,然后再通过父子组件传值将其传给Home.vue,然后首页就能通过this.$refs.scroll.refresh()拿到这个值,但是这样就特别麻烦。我们也可以用Vuex对象,它可以用来记录一些状态,一旦GoodsListItem图片加载完成了以后,就改变Vuex里面的某一个属性,再让我们的首页里面应用这一属性,并让它实时监听我们Vuex里面的某个属性的改变,一旦这个属性发生变化,就让其执行this. $refs.scroll.refresh()。也就意味着我们用Vuex做了中间的一个通信,在GoodsListItem中拿到this. $store,就可以改变Vuex里面的属性,再让首页监听这个属性。另外,我们还可以用 事件总线 ,它和Vuex的作用很像,但是它不是用来管理状态的,它是用来管理事件的。我们通过this. b u s . bus. bus. emit(‘aaa’)向事件总线发送事件,然后我们可以在首页里面监听它发射出来的事件,用this. $bus.on(‘aaa’)对aaa这个事件进行监听。
所以在GoodsListItem.vue中发射事件:

  methods: {
    imageLoad() {
      this.$bus.$emit('itemImageLoad')
    }
  }

在我们的Home.vue中进行监听:

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

(之所以在mouted而不在created中是因为在created中很有可能是拿不到this. $ refs.scroll)
但是在我们的程序中是没有$bus这种东西的,所以我们需要以下操作:
在 main.js 中将 $bus 绑定到 vue 原型上

Vue.prototype.$bus = new Vue();

再到scroll.vue中封装refresh()方法

refresh(){
      this.scroll.refresh()
    },

最终的结果:
请添加图片描述
总结:
解决首页中Better-Scroll可滚动区域的问题
●Better-Scroll在决定有多少区域可以滚动时,是根据scrollerHeight属性决定

  • scrollerHeight属性是根据放Better-Scroll的content中的子组件的高度
  • 但是我们的首页中,刚开始在计算scrollerHeight属性时,是没有将图片计算在内的
  • 所以,计算出来的结果是错误的(1400+)
  • 后来图片加载进来之后有了新的高度但是scrollerHeight属性并没有进行更新。
  • 所以滚动出现了问题

●如何解决这个问题了?

  • 监听每一张图片是否加载完成,只要有一张图片加载完成了,执行一 次refresh()
  • 如何监听图片加载完成了?
    原生js监听:img.onload = function) {}
    vue中监听:@load=‘方法’
    ●调用scroll的refresh()

●如何将GoodsListltem.vue中 的事件传入到Home.yue中

 * 因为涉及到非父子组件的通信,所以这里我们选择了事件总线
    - bus->.总线
    - Vue.prototype.$bus = new Vue()
    - this.bus.emit(事件名称',参数)
    - this.bus.on(事件名称,回调函数(参数))

优化:
我们监听item中图片加载完成这个事件调用的频率很高

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

在home组件中的methods中

  //防抖函数
    debounce(func,delay){
      let timer=null;
      return function(...args){
        if(timer) clearTimeout(timer)

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

然后在mouted中使用该防抖函数

  mounted() {
    this.$bus.$on('itemImageLoad',()=>{
      this.$refs.scroll.refresh()
    })
      const refresh=this.debounce(this.$refs.scroll.refresh,500)
      this.$bus.$on('itemImageLoad',()=>{
          refresh()
    })
  },

总结:

  • 对于refresh非常频繁的问题,进行防抖操作
    - 防抖函数起作用的过程:
    ■如果我们直接执行refresh,那么refresh函数会被执行30次.
    ■可以将refresh函数传入到debounce函数中, 生成一个新的函数.
    ■之后在调用非常频繁的时候,就使用新生成的函数
    ■而新生成的函数,并不会非常频繁的调用,如果下一次执行来的非常快,那么会将上一次取消掉
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纵有千堆雪与长街

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值