Vue3组件在Storybook中报Cannot read properties of undefined(style)错求助
Vue3 + Storybook DOM操作报错问题
问题详情
我正在使用Vue3结合Storybook进行开发,在组件中编写了如下div_show函数:
function div_show(id) { const elements = document.getElementsByClassName("innerright"); for (let i = 0; i < elements.length; i++) { if (i + 1 != id) { elements[i].style.display = "none"; } } elements[id - 1].style.display = "block"; }
该函数在App.vue中运行完全正常,但在Storybook中使用该组件时,出现错误:Error Cannot read properties of undefined (reading 'style')。
解决方案
原因
Storybook环境下组件的渲染时机、DOM加载状态和App.vue存在差异,调用div_show时可能存在两种情况:
- 类名为
innerright的DOM元素还未完成挂载,导致elements为空数组 - 传入的
id值超出了elements的长度范围,使得elements[id-1]为undefined
修复方案
方案1:给DOM操作添加安全校验
直接在原函数中增加存在性判断,避免访问undefined的属性:
function div_show(id) { const elements = document.getElementsByClassName("innerright"); // 校验id是否在有效范围内 if (!elements.length || id < 1 || id > elements.length) return; for (let i = 0; i < elements.length; i++) { if (elements[i]) { elements[i].style.display = (i + 1 === id) ? "block" : "none"; } } }
方案2:改用Vue响应式控制(推荐)
直接操作DOM不符合Vue的响应式设计理念,改用响应式数据控制显示更可靠:
- 在组件中定义响应式变量:
import { ref } from 'vue'; const activeId = ref(1); // 默认激活第一个元素
- 模板中通过响应式数据绑定显示状态:
<div v-for="(item, index) in yourDataList" :key="index + 1" class="innerright" :style="{ display: activeId === index + 1 ? 'block' : 'none' }" > <!-- 组件内容 --> </div>
- 修改
div_show函数为更新响应式变量:
function div_show(id) { activeId.value = id; }
方案3:确保DOM挂载完成后再调用函数
如果必须保留DOM操作逻辑,需确保组件已挂载完成:
- 在Vue组件中,将调用逻辑放在
onMounted钩子内:
import { onMounted } from 'vue'; onMounted(() => { // 这里调用div_show或确保触发div_show的事件在挂载后执行 });
- 在Storybook的故事文件中,可使用
waitFor确保DOM加载完成:
import { waitFor } from '@storybook/testing-library'; export default { title: 'YourComponent', component: YourComponent, }; const Template = (args) => ({ components: { YourComponent }, setup() { return { args }; }, template: '<YourComponent v-bind="args" />', }); export const Default = Template.bind({}); Default.play = async ({ canvasElement }) => { await waitFor(() => canvasElement.querySelector('.innerright')); // 之后再执行触发div_show的操作 };
内容的提问来源于stack exchange,提问作者Palak Sharma
相关产品推荐
相关产品推荐

