uni-app [Vue warn]: Error in nextTick: "TypeError: Cannot read property 'dataset' of null"

发布于 1周前 作者 zlyuanteng 来自 Uni-App

uni-app [Vue warn]: Error in nextTick: “TypeError: Cannot read property ‘dataset’ of null”

示例代码:

this.$nextTick(() => {  
  console.log('打印了组件变量值:', this.$refs.MyComponent.X)  
})

操作步骤:

  • 点击点我进入A包

预期结果:

  • 不报错,能打印出1

实际结果:

报错
[Vue warn]: Error in nextTick: "TypeError: Cannot read property 'dataset' of null"
(found in packageA/pages/pageA/index.vue)

bug描述:

项目配置分包,小程序中分包A中A页面使用分包B中的组件,A页面配置了componentPlaceholder。

在A的onLoad周期中使用$nextTick获取组件内部的值报错。

[Vue warn]: Error in nextTick: "TypeError: Cannot read property 'dataset' of null"
(found in packageA/pages/pageA/index.vue)
信息类型 信息
产品分类 uniapp/小程序/微信
PC开发环境操作系统 Mac
PC开发环境操作系统版本号 macOS Sequoia 15.1
第三方开发者工具版本号 2.0.2-4000820240401001
基础库版本号 3.6.6
项目创建方式 CLI
CLI版本号 ~4.5.0

10 回复

/packageA/index.vue

<template> ... <MyComponent ref="MyComponent"></MyComponent> ... </template>

<script> ... import MyComponent from '@/packageB/components/MyComponent/MyComponent.vue' ... ... onLoad() { this.$nextTick(() => { console.log('打印了组件变量值:', this.$refs.MyComponent.X) }) }, ... </script>

/packageB/components/MyComponent/MyComponent.vue

<template> ... </template> <script> ... data () { return { X: 1 } }, ... </script> pages.json


{
“path”: “pages/pageA/index”,
“style”: {
“navigationBarTitleText”: “A页面”,
“componentPlaceholder”: {
“my-component”: “view”
}
}
},


针对小程序处理,能否有个监听到所有组件异步化加载完成后的页面生命周期

// /packageA/index.vue的页面周期里面这样写在微信开发者工具里面不会报错,但是在预览真机里面会报错


onLoad() {
this.$nextTick(() => {
setTimeout(() => {
console.log(‘打印了组件变量值:’, this.$refs.MyComponent.X)
}, 200);
})
},

你试下这样子写 this.$nextTick(function() { setTimeout(() => { console.log(‘打印了组件变量值:’, this.$refs.MyComponent.X) }, 200); })

或者在onReady生命周期执行看看

感谢,好像没有api获取组件加载完成后执行的,settimeout有可能网络不好存在获取不到组件实例的情况

可以使用uni.$emit这种工具,在组件中执行完成之后使用uni.$emit触发你页面上的uni.$on监听的数据这样来实现

当组件很多且网络比较慢的时候用这种感觉比较好


onLoad() {
await this.isComponentLoaded()
this.$nextTick(() => {
console.log(‘在nextTick中获取到的组件:’, this.$refs)
})
console.log(‘在onLoad中获取到的组件:’, this.$refs)
},


methods: {
isComponentLoaded() {
return new Promise((resolve, reject) => {
let timer = setInterval(() => {
try {
// 使用跨包组件如果组件没有加载完成,在onLoad周期里面是用this.$refs会报错,使用计时器可以判断跨包组件是否加载完成
if (this.$refs) {
resolve()
clearTimeout(timer)
}
} catch (error) {

      }  
    }, 500);  
  })  
}  

}

遇到 uni-app 中的 [Vue warn]: Error in nextTick: "TypeError: Cannot read property 'dataset' of null" 错误,通常意味着在 nextTick 回调函数中尝试访问一个不存在的 DOM 元素的 dataset 属性。这种情况经常发生在 DOM 元素尚未渲染完成或已被移除时尝试访问它。

下面是一个可能导致这种错误的代码示例以及如何修复它:

示例代码(可能导致错误)

<template>
  <view ref="myElement" :data-info="someInfo"></view>
</template>

<script>
export default {
  data() {
    return {
      someInfo: 'initial info'
    };
  },
  mounted() {
    this.someInfo = 'updated info';
    this.$nextTick(() => {
      // 假设此时 DOM 元素因为某些原因(如条件渲染)尚未渲染或已被移除
      const element = this.$refs.myElement;
      console.log(element.dataset.info); // 这里可能抛出 TypeError
    });
  }
};
</script>

修复方法

  1. 确保元素存在:在访问 dataset 之前,检查元素是否存在。
  2. 使用条件渲染时的注意事项:如果元素是条件渲染的,确保在访问它之前条件已经满足。

修复后的代码

<template>
  <view v-if="showElement" ref="myElement" :data-info="someInfo"></view>
</template>

<script>
export default {
  data() {
    return {
      someInfo: 'initial info',
      showElement: true // 控制元素是否渲染
    };
  },
  mounted() {
    this.someInfo = 'updated info';
    this.$nextTick(() => {
      const element = this.$refs.myElement;
      if (element) {
        console.log(element.dataset.info); // 安全访问
      } else {
        console.warn('Element not found');
      }
    });

    // 模拟在某些情况下隐藏元素
    setTimeout(() => {
      this.showElement = false;
    }, 2000);
  }
};
</script>

在这个修复后的示例中,我们添加了 v-if="showElement" 来控制元素的渲染,同时在 nextTick 回调中检查 this.$refs.myElement 是否存在。这样可以有效避免尝试访问一个不存在的 DOM 元素的属性时抛出错误。

此外,考虑到实际应用中可能存在的异步更新和条件渲染逻辑,确保在访问任何 DOM 属性之前,相关的元素确实已经渲染并可用,是非常重要的。

回到顶部