vue 无法监听scroll事件

大家好,小弟是刚接触vue的小菜鸟,在使用过程中发现一个问题,就是在一个组件上监听scroll事件无效,有滚动操作也没有触发。
监听scroll事件尝试使用了v-on和window addEventListener方法,都不行(同样方法监听touchmove就可以成功),使用方法如下:
通过v-on操作

<template>
<div class="table-container" @scroll=handleScroll>
    <div class="headcol">
        <table>
            <thead>
                <tr >
                    <td v-for="c in list.header">
                        {{c}}
                    </td>
                </tr>
            </thead>
            <tbody>
                <tr  v-for="r in list.rows">
                    <td v-for="c in r">
                        {{c}}
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</div>
</template>

通过eventlistener操作:

        created() {
            window.addEventListener('scroll', this.handleScroll);
        },

还有一个问题,就是同样在这个组件里注册的touchmove事件handler里读取到的scrollTop一直为0。
另外,就是offsetHeight用document.documentElement.offsetHeight和document.body.offsetHeight一直都获取不到。不知道是什么原因。

通过touchmove事件获取scroTop等相关数值的操作:

            handleTouchMove(e) {
                let scrollTop = document.body.scrollTop;
                let clientHeight = document.body.clientHeight;

                console.log("shoplist scrollTop %d, clientHeight %d“, 
                            scrollTop, clientHeight);
            },

以上两个问题查找了很多文章都没有什么帮助,所以还请大家多指教。感谢感谢。

阅读 52.7k
评论 更新于 2019-06-13
    15 个回答
    Delin
    • 158

    给后面的人多一个解决方案,第三个参数加上true,能成功监听。window.addEventListener('scroll', this.handleScroll, true);

    评论 赞赏 2018-04-25
      holdno
      • 1.7k

      说一下思路

      <!--添加ref-->
      <div class="headcol" ref="viewBox">
          <table>
              <thead>
                  <tr >
                      <td v-for="c in list.header">
                          {{c}}
                      </td>
                  </tr>
              </thead>
              <tbody>
                  <tr  v-for="r in list.rows">
                      <td v-for="c in r">
                          {{c}}
                      </td>
                  </tr>
              </tbody>
          </table>
      </div>
      // 首先通过$refs获取dom元素
      this.box = this.$refs.viewBox
      // 监听这个dom的scroll事件
      this.box.addEventListener('scroll', () => {
        console.log(this.$refs.viewBox.scrollTop)
      }, false)
      评论 赞赏 2017-04-19

        v-on为什么绑定不了滚动事件?
        答:可能table-container盒子里面并没有滚动条。
        至于addEventListener试试把它写在mounted钩子里看一下,我也不清楚

        评论 赞赏 2017-04-19

          vue监听滚动事件要使用@scroll.native="",直接使用@scroll无效,查了很久发现网上的全是利用原生事件监听的,真是坑爹。

          评论 赞赏 2017-12-28

            兼容性问题,如果这样,let tpScrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop,打印出来就不是0了。

            评论 赞赏 2018-05-30
              JearyCheung
              • 3
              • 新人请关照

              今天我也刚好遇到这个问题,把它做成了 vue 组件,带滚动动画完美解决,以下是完整代码:

              export default {
                name: 'ScrollTop',
                data() {
                  return {
                    // 定义滚动条默认位置
                    scrollTop: null,
              
                    // 定义按钮默认状态
                    isScrollTop: false
                  }
                },
                props: {
                  el: String
                },
                mounted() {
                  // 监听滚动事件
                  window.addEventListener('scroll', () => {
                    this.scrollTop = document.documentElement.scrollTop ||
                                      window.pageYOffset ||
                                      document.body.scrollTop ||
                                      document.querySelector(this.el).scrollTop;
              
                    // 控制滚动按钮的隐藏或显示
                    if (this.scrollTop > 150) {
                      this.isScrollTop = true;
                    } else {
                      this.isScrollTop = false;
                    }
                  }, true);
                },
                methods: {
                  /**
                   * 滚动到顶部
                   */
                  scrollToTop() {
                    let $this = this;
              
                    // 返回顶部动画特效
                    setTimeout(function animation() {
                      if ($this.scrollTop > 0) {
                        setTimeout(() => {
              
                          // 步进速度
                          $this.scrollTop = $this.scrollTop - 30;
              
                          // 返回顶部
                          if(document.documentElement.scrollTop > 0) {
                            document.documentElement.scrollTop = $this.scrollTop - 30;
                          } else if (window.pageYOffset > 0) {
                            window.pageYOffset = $this.scrollTop - 30;
                          } else if (document.body.scrollTop > 0) {
                            document.body.scrollTop = $this.scrollTop - 30;
                          } else if (document.querySelector($this.el).scrollTop) {
                            document.querySelector($this.el).scrollTop = $this.scrollTop - 30;
                          }
              
                          animation();
                        }, 1);
                      }
                    }, 1);
                  }
                }
              };
              评论 赞赏 2018-10-17

                我也遇到一样的问题了。的确@scroll监听不到。
                我按照你说的去监听了touchmove。scrollTop的值也一直是0.
                你可以试试window.pageYOffset,我用这个能获取值

                评论 赞赏 2017-05-11
                  lady
                  • 334
                  created() {
                          window.addEventListener('scroll', this.handleScroll);
                      },
                          
                          
                    这里的this指向window了。
                    写成
                          created() {
                          let _this = this,
                          window.addEventListener('scroll', _this.handleScroll);
                      },
                  评论 赞赏 2018-03-21
                    阳光boy
                    • 5
                    • 新人请关照

                    用原生事件就可以监听啊,
                    <child @scroll.native="scrollHandler"></child>

                    methods: {

                    scrollHandler (el) {
                        console.log(el)
                    }

                    }

                    评论 赞赏 2018-04-12
                      土豆哪里去挖
                      • 2
                      • 新人请关照

                      抄一些前面的代码,需要加nextTick到渲染完成才可以添加

                      created(){
                      this.$nextTick(function(){
                      let box = this.$refs.viewBox
                      // 监听这个dom的scroll事件
                      let _this = this
                      box.addEventListener('scroll', () => {
                      console.log(this.$refs.viewBox.scrollTop)
                      this.$refs.viewBox.addEventListener('scroll', _this.handleScroll)
                      }, false)
                      }

                      评论 赞赏 2018-05-16

                        早上也遇到了这个问题 提供一下解决方案吧。
                        mounted(){

                        window.addEventListener('scroll',this.loadMore,true);

                        },
                        methods:{

                        loadMore(){
                            clearTimeout(this.timer);
                            this.timer=setTimeout(()=>{
                                var clientHeight=document.documentElement.clientHeight; //document.documentElement获取数据
                                var scrollTop=document.documentElement.scrollTop; //document.documentElement获取数据
                                var scrollHeight=document.documentElement.scrollHeight;//document.documentElement获取数据
                                if(clientHeight+scrollTop+20>=scrollHeight){
                                    this.pageIndex++;
                                    this.getBooks();
                                }
                            },13);

                        },
                        数据能完美获取到

                        评论 赞赏 2018-05-31
                          初醒的小狮子
                          • 2
                          • 新人请关照

                          有一种情况,created()需要在keep-alive包裹之后才会执行,所以查看app.vue中keep-alivevia标签是否有exclude,排除了这个组件对应的路由,去掉这个就可以执行created(),从而会执行scroll事件

                          评论 赞赏 2018-07-17

                            我也遇到了,我的情况是区域滚动,只有在安卓手机微信浏览器里 绑定scroll事件有问题。解决办法是在mounted 里面 $nextTick()里面用原生addEventListener绑定。

                            评论 赞赏 2019-04-15

                              @scroll方法要生效,元素的overflow属性要设置为scroll

                              评论 赞赏 2019-07-19

                                最外层要加上这个, overflow-y: auto; 移动端还要有 -webkit-overflow-scrolling: touch;我是 @scroll="scroll(e)" 这么绑定的

                                评论 赞赏 2019-08-08
                                  撰写回答

                                  登录后参与交流、获取后续更新提醒