Vue3报错:runtime-dom.esm-bundler.js:33 无法读取null的parentNode属性
问题原因及解决办法
为啥顶层用await会报错?
<script setup>里直接写顶层await会把组件变成异步组件,这时候组件的DOM还没挂载好,Vue渲染模板的时候试图访问不存在的DOM节点的parentNode,就会抛出那个"Cannot read properties of null"的错误。异步组件的初始化时机比普通组件晚,模板渲染时DOM环境还没准备到位。
正确的处理方式
方法1:用onMounted钩子(你已经试过的有效方案)
把数据请求放到组件挂载完成后的钩子里面,这时候DOM已经就绪,就不会有DOM相关的报错了。另外注意要把数据用ref包装成响应式对象,不然模板没法响应数据变化:
<script setup lang="ts"> import { fetchProducts } from '@/services/product.ts'; import { ref, onMounted } from 'vue'; import { IProduct } from '@/interfaces/product.interface.ts'; const productsRef = ref<IProduct[]>([]); onMounted(async () => { productsRef.value = await fetchProducts(); }); </script> <template> <div class="px-4 py-6" v-if="productsRef.length">a</div> </template>
方法2:一定要用顶层await?(异步组件场景)
如果确实需要保留顶层await(比如组件要异步加载其他依赖),得确保模板里处理好加载状态,别直接依赖未初始化的DOM:
<script setup lang="ts"> import { fetchProducts } from '@/services/product.ts'; import { ref } from 'vue'; import { IProduct } from '@/interfaces/product.interface.ts'; const productsRef = ref<IProduct[]>(await fetchProducts()); </script> <template> <div v-if="productsRef.length" class="px-4 py-6">a</div> <div v-else>加载中...</div> </template>
不过普通数据请求还是更推荐用onMounted,这种方式适合组件本身需要异步加载的场景。
额外提醒
- 你之前的代码里,直接把
await fetchProducts()赋值给Ref<IProduct[]>是错的,因为await之后拿到的是普通数组,不是响应式的Ref对象,必须用ref()包装才能让模板响应数据变化。 - 模板里的
v-if="productsRef"没啥用,因为ref对象本身永远不会是null,改成判断数组长度productsRef.length才合理。
内容的提问来源于stack exchange,提问作者huan feng
相关产品推荐
相关产品推荐

