Storybook 8+Vue3+TS环境下如何在Story中填充Vue组件插槽子组件
问题描述
我用Vue 3开发了一个组件,需要根据上下文展示不同子组件,采用插槽是Vue 3的正确实现方式。升级到支持“一等Vue支持”的Storybook 8后,原来在Storybook 7中可用的插槽填充语法失效了,需要迁移指导。
我是Vue和Storybook新手,希望得到在Story中为Vue组件插槽动态填充子组件的示例。
我的Vue组件代码(除插槽外功能正常):
<template> <div class="alert" :id="props.identifier" :class="[alertStyleClass, alertWidthClass, alertLayoutClass]"> <Icon v-if="props.icon" class="alert__icon" :name="props.icon" /> <div class="alert__main" v-if="slots.main && !props.message"> <slot name="main"> </slot> </div> <div class="alert__main" v-else v-html="props.message"></div> <div class="alert__actions" v-if="slots.actions"> <slot name="actions"> </slot> </div> </div> </template>
原来Storybook 7中可行但现在失效的Story代码:
export const CheckboxNotification: Story = { args: { identifier: '', style: AlertStyle.Information }, parameters: { slots: { main: { description: 'Main slot', components: { CheckboxComponent }, template: `<CheckboxComponent label="Label" identifier="AlertCheckbox" value="true" name="AlertCB" />` } } } }
我尝试过另一种写法,但插槽只显示字面字符串,没有编译成子组件:
export const CheckboxNotification: Story = { args: { identifier: '', style: AlertStyle.Information, main: `<CheckboxComponent label="Label" identifier="AlertCheckbox" value="true" name="AlertCB" />` } }
我不想修改Vue组件来适配Storybook,希望仅通过修改Story代码解决问题,若有遗漏关键信息请告知。
解决方案
Storybook 8对Vue的插槽机制做了调整,移除了旧的parameters.slots写法,改用更贴近Vue原生的方式传递插槽内容,以下是两种可行方案:
方法1:使用render函数(推荐)
直接通过Vue的渲染逻辑编写模板,完全贴合Vue原生插槽语法,兼容性最好:
import { h } from 'vue'; import Alert from './Alert.vue'; import CheckboxComponent from './CheckboxComponent.vue'; export const CheckboxNotification: Story = { args: { identifier: '', style: AlertStyle.Information }, render: (args) => ({ components: { Alert, CheckboxComponent }, setup() { return { args }; }, template: ` <Alert :identifier="args.identifier" :style="args.style"> <template #main> <CheckboxComponent label="Label" identifier="AlertCheckbox" value="true" name="AlertCB" /> </template> </Alert> ` }) };
方法2:通过args传递VNode
如果偏好使用args的方式,可以直接传递组件的VNode实例代替字符串模板:
import { h } from 'vue'; import Alert from './Alert.vue'; import CheckboxComponent from './CheckboxComponent.vue'; export const CheckboxNotification: Story = { args: { identifier: '', style: AlertStyle.Information, main: h(CheckboxComponent, { label: "Label", identifier: "AlertCheckbox", value: true, name: "AlertCB" }) } };
关键注意点
- 确保在Story文件中正确导入所有需要用到的子组件(比如示例中的
CheckboxComponent) - 若使用模板语法,要遵循Vue 3的插槽简写规则(
#main对应v-slot:main) - 两种方案都不需要修改原Vue组件,完全通过Story代码适配Storybook 8的新机制
内容的提问来源于stack exchange,提问作者Toby Hope
相关产品推荐
相关产品推荐

