vue的dom元素绑定了ref找不到getBoundingClientRect

绑定滚动事件,获取元素距离屏幕高度,经常出现报错,无此functions

<div ref="showMore"></div>
mounted:function () {
      window.addEventListener('scroll', this.handleScroll);
    }
handleScroll(){
          this.$nextTick(()=>{
              console.log(this.$refs.showMore.getBoundingClientRect())
          })
      }

加不加this.$nextTick都会出现错误。。有时候滚动如1所示没错,有时候滚动的时候就如2所示,报错: Error in nextTick: "TypeError: Cannot read property 'getBoundingClientRect' of undefined"
图片描述

console.log(this.$refs)的结果:

图片描述

ps:发现,从一个页面跳转到当前页面每次滚动都会报错,,但是直接刷新下本页面再滚动就不会报错。。。。。刷新n次都不会报错

阅读 22.1k
12 个回答

使用 Vantvan-tabs$router.push 时出现了,复现流程比较复杂。

image.png

其中 TypeError: Cannot read property 'getBoundingClientRect' of undefined 经过定位是在 VantgetVisibleHeight 方法中没有获取到el的原因。

// webpack:///./node_modules/vant/es/utils/dom/scroll.js?a8c1
export function getVisibleHeight(el) {
  if (isWindow(el)) {
    return el.innerHeight;
  }

  return el.getBoundingClientRect().height;
}

大概率是 Vant 的问题。倒不是bug,缺少了些边界值判断吧。最后是通过添加一个 setTimeout(() => { /* something */ }, 0) 解决了问题。

应该是你在某个页面内绑定了window滚动事件,this.$refs.showMore是该页面下才能获取的对象,切换页面时window绑定的事件还在,但页面销毁,页面中的this.$refs.showMore找不到就报错了

建议在组件内的导航守卫beforeRouteLeave添加对window的解绑

换一个钩子看看 用created钩子

created:function () {
  window.addEventListener('scroll',event => this.handleScroll());
}

你把 this.$refs 打印出来试试
console.log(this.$refs),你看看里面都是些啥,应该就能解决了。

scroll 函数加一个节流吧,可能滚动的太频繁。

this.$el.querySelector('.your_element_classNmae').getBoundingClientRect()
新手上路,请多包涵

你好,请问你是如何解决的

大佬解决了请分享一下

新手上路,请多包涵

我的是注释了ref="xxx",而mounted方法又使用了这个引用才导致的,非常感谢

新手上路,请多包涵

实际上使用

 window.addEventListener('scroll', this.handleScroll);

进行绑定的时候,你跳转到其他页面进行滚动一样会触发

 window.addEventListener('scroll', this.handleScroll);

这个方法
解决方案,判断是否处在当前页面

handleScroll(){
        if(!this.$refs.showMore) return;
          this.$nextTick(()=>{
              console.log(this.$refs.showMore.getBoundingClientRect())
          })
      }

只要不是当前你想要的页面触发的,就return

今天同样遇见这样的问题。
在使用
beforeDestroy () {

window.removeEventListener('scroll', this.handleScroll)

}
后还是会报错
后来发现问题出在removeEventListener上
查询了一下element.removeEventListener(useCapture)
useCapture 可选。布尔值,指定事件是否在捕获或冒泡阶段执行。可能值:true - 事件句柄在捕获阶段执行false- false- 默认。事件句柄在冒泡阶段执行
因为useCapture默认为false,所以在销毁的时候捕获冒泡阶段时改为true就行了。
解决方式:
beforeDestroy () {

window.removeEventListener('scroll', this.handleScroll,true)

}

新手上路,请多包涵

<template>

<div class="page-index" ref="refPage">
<!-- html代码 -->
</div>

</template>

// -------js
export default {

computed: {
    refPage(){
        return this.$refs.refPage
    }
},
methods: {
    onPageScroll(){
        console.log(this.refPage,'ref')
        this.offsetTop = this.refPage.getBoundingClientRect().top
    },
},
mounted(){
    window.addEventListener('scroll', this.onPageScroll, true)
},

}

原因嘛,你在 onPageScroll 事件里打印 (this.refPage属性) 就会发现 每一次window监听的滚动事件都在重绘页面,所以每一次滚动了马上去执行onPageScroll事件,但此时page被更新的时候ref又去重新获取,且此时page未完全停止滚动,就会undefined,对象都没有,自然也就没有getBoundingClientRect() 方法了。

用vue computed 将ref做计算,就没有报错了,每一次调用onPageScroll事件都会先去计算,所以控制台会console.log(this.refPage,'ref')在这一行的时候,先打印ref ,过一会才会输出
div.... ref 这样。

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