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);
            },

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

阅读 95.3k
18 个回答

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

说一下思路

<!--添加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)

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

今天我也刚好遇到这个问题,把它做成了 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);
    }
  }
};

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

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

created() {
        window.addEventListener('scroll', this.handleScroll);
    },
        
        
  这里的this指向window了。
  写成
        created() {
        let _this = this,
        window.addEventListener('scroll', _this.handleScroll);
    },
新手上路,请多包涵

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

methods: {

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

}

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

没一个有用? 太难了;

自己用一個笨方法完成了:

<div class="desc" ref="scrollBox"></div>
mounted() {
  window.addEventListener('scroll', this.handleScroll,true);
},
destroyed(){
  window.removeEventListener('scroll', this.handleScroll,true);
},
methods: {
  handleScroll() {
    let _blTop = this.$refs.scrollBox.getBoundingClientRect().top
 var scrollTop = window.pageYOffset
 console.log(_blTop,scrollTop)
    if (scrollTop > 600) {
      // do something...
 } else {
      // do something...
 }
  }
}

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

抄一些前面的代码,需要加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)
}

早上也遇到了这个问题 提供一下解决方案吧。
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);

},
数据能完美获取到

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

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

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

vue 无法监听scroll事件

同样遇到这个问题,现在大概明白了,正常来说 scroll 事件在冒泡阶段是可以捕获到的,现在得改成捕获阶段才行原因是监听的元素并不是滚动容器,而是在监听元素的后代,仔细想想第三个参数是不是这样。

提供两种解决方法吧,第一种是审查元素找到相对最外层的 overflow: auto/scroll 去掉,保证你要的滚动容器是最外层;第二种是在滚动容器加 ref 属性,获取 getBoundingClientRecttop值,代码可以参考楼上的朋友们提供的。

新手上路,请多包涵

在最外层盒子上嘛加加上这两个属性 scroll事件就能监听到滚动体的高度了
height: 100%;
overflow: scroll;
再通过e.target.scrollTop实时拿到滚动条的高度

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏