因为上一次解决的滚动区域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函数中, 生成一个新的函数.
■之后在调用非常频繁的时候,就使用新生成的函数
■而新生成的函数,并不会非常频繁的调用,如果下一次执行来的非常快,那么会将上一次取消掉