You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 09:20:39