web-dev-qa-db-ja.com

VueJSコンポーネントでウィンドウスクロールイベントをリッスンする方法は?

Vueコンポーネントでウィンドウスクロールイベントをリッスンしたい。ここに私がこれまで試したものがあります:

<my-component v-on:scroll="scrollFunction">
    ...
</my-component>

コンポーネントメソッドでscrollFunction(event)が定義されていますが、機能していないようです。

誰もこれを行う方法を知っていますか?

ありがとう!

32
jeerbl

実際に解決策を見つけました。コンポーネントが作成されたときにscrollイベントにイベントリスナーを追加し、コンポーネントが破棄されたときにイベントリスナーを削除します。

export default {
  methods: {
    handleScroll (event) {
      // Any code to be executed when the window is scrolled
    }
  },
  created () {
    window.addEventListener('scroll', this.handleScroll);
  },
  destroyed () {
    window.removeEventListener('scroll', this.handleScroll);
  }
}

お役に立てれば!

84
jeerbl

要件はコンポーネントにありますが、コンポーネントではなくボディに追加することになりました。もちろん、特定の要素でも同様に行うことができますが、ちょっと... Vueカスタムコンポーネントで直接機能するものです。

 <MyCustomComponent nativeOnScroll={this.handleScroll}>

または

<my-component v-on:scroll.native="handleScroll">

そしてhandleScrollのメソッドを定義します。シンプル!

6
kushalvm

私の経験では、スクロールでイベントリスナを使用すると、そのイベントストリームへのパイプが原因で多くのノイズが発生する可能性があり、大きなhandleScroll関数を実行するとパフォーマンスの問題が発生する可能性があります。

私はここで最も高い評価の回答でここに示すテクニックをよく使用しますが、その上にデバウンスを追加します。通常、100msがUX比に対して良好なパフォーマンスをもたらします。

Lodashのデバウンスが追加された最高評価の回答を使用した例を次に示します。

import debounce from 'lodash/debounce';

export default {
  methods: {
    handleScroll(event) {
      // Any code to be executed when the window is scrolled
      this.isUserScrolling = (window.scrollY > 0);
      console.log('calling handleScroll');
    }
  },

  created() {
    this.handleDebouncedScroll = debounce(this.handleScroll, 100);
    window.addEventListener('scroll', this.handleDebouncedScroll);
  },

  beforeDestroy() {
    // I switched the example from `destroyed` to `beforeDestroy`
    // to exercise your mind a bit. This lifecycle method works too.
    window.removeEventListener('scroll', this.handleDebouncedScroll);
  }
}

100の値を0および1000に変更して、handleScrollが呼び出される方法とタイミングの違いを確認してください。

ボーナス:vue-scrollなどのライブラリを使用すると、さらに簡潔で再利用可能な方法でこれを実現することもできます。 Vueのカスタムディレクティブをまだ見たことがない場合は、これらのディレクティブを学ぶのに最適です。 https://github.com/wangpin34/vue-scroll をご覧ください。

これは、Sarah DrasnerによるVueドキュメントの素晴らしいチュートリアルでもあります。 https://vuejs.org/v2/cookbook/creating-custom-scroll-directives.html

5
agm1984

私はこの機能を何度も必要としてきたので、 mixin に抽出しました。次のように使用できます。

import windowScrollPosition from 'path/to/mixin.js'

new Vue({
  mixins: [ windowScrollPosition('position') ]
})

これにより、Vueインスタンスにリアクティブpositionプロパティ(好きな名前を付けることができます)が作成されます。このプロパティには、[x,y]配列としてウィンドウのスクロール位置が含まれます。

このCodeSandboxデモ で自由に遊んでください。

ミックスインのコードは次のとおりです。完全にコメントされているので、どのように機能するかを理解するのはそれほど難しくないはずです。

function windowScrollPosition(propertyName) {
  return {
    data() {
      return {
        // Initialize scroll position at [0, 0]
        [propertyName]: [0, 0]
      }
    },
    created() {
      // Only execute this code on the client side, server sticks to [0, 0]
      if (!this.$isServer) {
        this._scrollListener = () => {
          // window.pageX/YOffset is equivalent to window.scrollX/Y, but works in IE
          // We round values because high-DPI devies can provide some really nasty subpixel values
          this[propertyName] = [
            Math.round(window.pageXOffset),
            Math.round(window.pageYOffset)
          ]
        }

        // Call listener once to detect initial position
        this._scrollListener()

        // When scrolling, update the position
        window.addEventListener('scroll', this._scrollListener)
      }
    },
    beforeDestroy() {
      // Detach the listener when the component is gone
      window.removeEventListener('scroll', this._scrollListener)
    }
  }
}
2
Loilo