如何在Vue组件Story中触发Storybook暗色模式channel事件
实现方法
先修正preview.js的现有错误
你当前的preview.js存在两个问题导致监听无法生效:
- 刚执行
channel.on绑定监听就立刻调用channel.off解绑,监听逻辑还没等事件触发就被移除 channel.off需要传入和channel.on完全相同的函数引用才能正确解绑,你传入了新的匿名函数,既无法解绑原有监听,也没有实际执行意义
修正后的preview.js代码如下:
// .storybook/preview.js import { addons } from '@storybook/addons'; const channel = addons.getChannel(); const handleDarkModeChange = (isDark) => { console.log('暗色模式状态:', isDark ? '激活' : '关闭'); // 在这里写实际的暗色模式切换逻辑,比如给根节点挂载dark类名 document.documentElement.classList.toggle('dark', Boolean(isDark)); }; // 绑定事件监听 channel.on('STORYBOOK_DARK_MODE_VUE', handleDarkModeChange);
如果后续需要解绑监听,把
handleDarkModeChange作为第二个参数传入channel.off即可,不要在初始化阶段就执行解绑。
修改Story文件,在组件事件回调中主动触发channel事件
Storybook的addon channel是独立的事件总线,组件本身的原生事件、storybook action事件都不会自动转发到channel,你需要在组件的onToggle回调里主动调用channel的emit方法发送事件。
修改后的story代码:
import BToggle from './Toggle.vue'; import { addons } from '@storybook/addons'; export default { name: 'Components/Toggle', component: BToggle, parameters: { docs: { description: { component: 'Nothing to see here', }, }, }, argTypes: { label: { control: { type: 'text' }, }, onToggle: { action: 'changed', }, }, }; const Template = (args) => ({ components: { BToggle }, props: Object.keys(args), setup() { const channel = addons.getChannel(); const handleToggle = (toggleValue) => { // 保留原有action日志能力,保证actions面板能正常收到事件 args.onToggle(toggleValue); // 向channel发送指定事件,把当前开关的布尔值作为参数传递 channel.emit('STORYBOOK_DARK_MODE_VUE', toggleValue); }; return { handleToggle }; }, template: '<b-toggle v-bind="$props" @onToggle="handleToggle"></b-toggle>', }); export const Default = Template.bind({}); Default.args = { label: 'default', };
关于两个dark mode插件的差异说明
- 通用版
storybook-dark-mode是跨框架适配的官方插件,内部使用的事件名不是STORYBOOK_DARK_MODE_VUE,而是插件内置常量导出的DARK_MODE_EVENT_NAME,对应值为storybook-dark-mode/toggle - 你安装的
storybook-dark-mode-vue是Vue生态的适配分支版本,才会使用STORYBOOK_DARK_MODE_VUE作为事件标识,两个插件的事件不要混用 - 如果你只需要使用Storybook工具栏自带的暗色模式切换按钮,不需要额外在组件内写emit逻辑,插件会自动触发对应事件,你只需要在preview.js的监听回调里写主题切换逻辑即可。上面的emit写法仅适用于你需要通过组件内的开关联动全局暗色模式的场景。
内容的提问来源于stack exchange,提问作者rugbert
相关产品推荐
相关产品推荐

