最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Observing scroll position with requestAnimationFrame in Vue - Stack Overflow

programmeradmin1浏览0评论

Currently im trying to implement requestAnimationFrame() in my code. My goal is to observe the current scrollPosition of the window and update a variable constantly.

Code of my Vue Single File Component:

<script>
   data() {
      return {
         scrollPosition: 0
      }
   },
   methods: {
      updateScrollPosition() {
         this.scrollPosition = window.scrollY
         window.requestAnimationFrame(this.updateScrollPosition())
      }
   },
   created() {
      this.updateScrollPosition()
   }
</script>

,js,console,output

I expected that the scrollPosition constanstly changes based on the actual window scroll position. But actually I get InternalError: "too much recursion". So basically I feel like I didnt really understood this requestAnimationFrame() function — need help. Thank you!

Currently im trying to implement requestAnimationFrame() in my code. My goal is to observe the current scrollPosition of the window and update a variable constantly.

Code of my Vue Single File Component:

<script>
   data() {
      return {
         scrollPosition: 0
      }
   },
   methods: {
      updateScrollPosition() {
         this.scrollPosition = window.scrollY
         window.requestAnimationFrame(this.updateScrollPosition())
      }
   },
   created() {
      this.updateScrollPosition()
   }
</script>

https://jsbin./gizamohuxu/edit?html,js,console,output

I expected that the scrollPosition constanstly changes based on the actual window scroll position. But actually I get InternalError: "too much recursion". So basically I feel like I didnt really understood this requestAnimationFrame() function — need help. Thank you!

Share Improve this question asked Sep 2, 2019 at 10:54 gustavgustav 4065 silver badges17 bronze badges 3
  • developer.mozilla/en-US/docs/Web/API/… – curious lad Commented Sep 2, 2019 at 10:58
  • so its not possible with requestAnimationFrame() ? – gustav Commented Sep 2, 2019 at 11:03
  • probably it is, but this is native api for scroll – curious lad Commented Sep 2, 2019 at 12:28
Add a ment  | 

2 Answers 2

Reset to default 4

You directly call updateScrollPosition() in your statement and pass the result to requestAnimationFrame:

window.requestAnimationFrame(this.updateScrollPosition());

You need to pass the function directly to requestAnimationFrame, e.g.:

// pass function to requestAnimationFrame
window.requestAnimationFrame(this.updateScrollPosition);

Then it'll work as expected.

Altough you should use the scroll event if you want to get notified when the user scrolls, you can subscribe to it via addEventListener:

new Vue({
  data() {
    return {
      scrollPosition: 0
    };
  },
  methods: {
    updateScrollPosition() {
      this.scrollPosition = window.scrollY;
    }
  },
  created() {
    window.addEventListener("scroll", this.updateScrollPosition);
  },
  beforeDestroy() {
    // remove listener again
    window.removeEventListener("scroll", this.updateScrollPosition);
  }
});

Also remember to clean up the registered listener with removeEventListener once you don't need it anymore.

I believe implementing this using requestAnimationFrame would actually be worse for browser performance.

Important

The above statement is incorrect. You can use requestAnimationFrame to throttle the scroll event to make it more efficient as seen on MDN.

You essentially created infinite loop and that's why the call stack was exceeded. I would listen to the scroll event using addEventListener on window.

Example

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!',
    scrollPosition: 0,
    ticking: false
  },
  methods: {
     updateScrollPosition() {
       this.scrollPosition = window.scrollY;   
       
       if (!this.ticking) {
          window.requestAnimationFrame(function() {
          
          // do something

          this.ticking = false;
        });

          this.ticking = true;
      }
     }
  },
  created() {    
    window.addEventListener('scroll', this.updateScrollPosition);
  }
})
#app {
  position: fixed;
  background: white;
  top: 0;
  left: 0;
  right: 0;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
<div id="app">
  {{ message }}
  {{ scrollPosition }}
</div>
  <div>scroll</div>
  <div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div><div>scroll</div>

<script src="https://cdnjs.cloudflare./ajax/libs/vue/1.0.16/vue.js"></script>
  
</body>
</html>

发布评论

评论列表(0)

  1. 暂无评论