天天看點

【VUE】在vue中使用@scroll監聽滾動事件,@scroll無效問題解決!

先說原因:大機率是因為滾動事件并不是在你@scroll的div上發生的,而是發生在document上

在網上看了一下vue中監聽滾動條滾動事件,清一色的使用document.addEventListener('scroll',function(){})

我是在做滾動條滑到底部時,自動加載更多的時候有這個需求。

我認為使用document.addEventListener會破壞vue的統一性,對我這種有輕微代碼強迫症的人來說,讓我感覺很不爽。而且這種做法,會讓你更加難以判斷是否滑動到底部了,特别是當你并不是整頁滾動,而是頁面中擁有一個fixed固定的頭部時。

在.vue的元件中

<template>
  <div class="body-container" @scroll="scrollEvent">
    <ul>
	<li></li>
	……
	<li></li>
    </ul>
  </div>
<template>
           
export default {
    name: 'demo',
    data () {
      return {
        msg: '',
      }
    },
    methods: {
      scrollEvent(e){
        console.log(e)
      },
    }
}
           

照上面的寫法,我發現即使我的li标簽足夠多,撐滿一頁,頁面滾動的時候并不能觸發到scrollEvent,是什麼原因呢?

經過仔細思考,猜想應該是滾動事件并不是在我<div class="body-container" @scroll="scrollEvent">這個div上觸發的,因為滾動條并沒有出現在我這個div上。這個div完全被li标簽撐起來了,産生滾動事件的就是document了。

于是做了一個小試驗,定義一個固定高度的div

<div style="height: 300px" @scroll="scrollEvent">
    <div style="height: 200px"></div>
    <div style="height: 200px"></div>
    <div style="height: 200px"></div>
</div>
           

當我在這個300px固定高度的div中滾動的時候,果然觸發了scrollEvent,問題原因找到了,接下來就是解決了。

隻要我能讓<div class="body-container" @scroll="scrollEvent">擁有固定高度,就能觸發滾動事件了。

但是固定高度怎麼給呢,各個廠商的手機螢幕高度都是不一樣的,總不能讓某些手機顯示不完全,或者底部留白白吧。

當然後辦法啦!就是吧html,body,.body-container{height:100%}這樣,我的.body-container就能繼承到document的高度了;

還有另一個辦法,讓.body-container使用fixed定位

.body-container{
    position: fixed;
    top:6rem;
    left: 0;
    right:0;
    bottom: 0;
    overflow: auto
}
           

因為上下左右的位置都固定了,是以div自然也就有了固定高度,此方法适用于頁面有一個固定高度的頭部導航,我項目中有一個6rem高的頭部導航,是以我采用了fixed定位。

接下來就是驗證是否滑到了底部

export default {
    name: 'demo',
    data () {
      return {
        msg: '',
      }
    },
    methods: {
      scroll(e){
        //滾動的像素+容器的高度>可滾動的總高度-100像素
        if(e.srcElement.scrollTop+e.srcElement.offsetHeight>e.srcElement.scrollHeight-100){ 
          this.loadMore();    //加載更多
        }
      },
    }
}
           

這樣就能比較清晰的判斷是否滾動到了底部。但是如果僅僅這樣寫,當滾動到底部100px内時,會觸發很多次加載更多,是以我們需要增加一些判斷條件

methods: {
      scroll(e){
        // !this.moreLoading 沒有在加載狀态,觸發加載更多時,把this.moreLoading置未true
        // !this.noMore 沒有更多的狀态為false,當我們取到的資料長度小于1頁的數量時,就沒有更多了資料了,把 this.noMore置為true,這樣就不會觸發無意義的加載更多了
        if(e.srcElement.scrollTop+e.srcElement.offsetHeight>e.srcElement.scrollHeight-100 && !this.moreLoading && !this.noMore){
          this.loadMore();
        }
      },
    }
           

至此,功能完美的實作了,而且沒有使用document.addEventListener破壞vue的完整性,感覺自己棒棒哒!