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

如何在StoryBook中Mock子组件以避免外部依赖请求?

问题:Mock子组件阻止动态导入第三方依赖导致的StoryBook运行失败

我在为ParentComponent编写StoryBook时遇到问题:该组件包含ChildComponent子组件,而ChildComponent里通过动态导入common-data-provider的DataProvider组件,这会调用其他仓库代码,导致StoryBook运行失败。

问题代码行:

components: {
  DataProvider:  () => import("common-data-provider"),// --> 问题所在行
}

相关代码示例

ParentComponent的StoryBook代码

import articlesFunds from "../__fixtures__/articles.json";

export default {
    component: ParentComponent,
    argTypes: {
        getConfigFilesDataProvider: {
            control: "object",
        },
    },
    args: {
        getConfigFilesDataProvider: () => new Promise((resolve) => setTimeout(() => resolve({ data: articlesFunds }))),
    },
};

export const Default = (args) => ({
    components: { ParentComopnent },
    props: Object.keys(args),
    template: `
        <ParentComopnent
        :data-provider="getConfigFilesDataProvider"
        />
    `,
});

ChildComponent代码

<template>
        <DataProvider :data="articles" />
        
</template>

<script>
export default {
    name: "ChildComponent",
    components: {
        DataProvider:  () => import("common-data-provider"),// --> 问题所在行
        ComponentB
    },
    props: {
        articles: {
            type: Array,
            required: true,
        },
    }
};
</script>

解决方法

方法1:在Story中直接替换ChildComponent为Mock版本

直接在ParentComponent的Story文件里定义一个Mock的ChildComponent,替换原组件,彻底避免触发动态导入逻辑:

import articlesFunds from "../__fixtures__/articles.json";
import ParentComponent from './ParentComponent.vue';

// 定义Mock的ChildComponent,模拟原组件的props即可
const MockChildComponent = {
  name: 'ChildComponent',
  props: ['articles'],
  // 可以根据需要模拟模板,比如展示传入的articles数据,或者简单占位
  template: '<div>Mocked Child Component: {{ articles.length }} items</div>'
};

export default {
    component: ParentComponent,
    argTypes: {
        getConfigFilesDataProvider: {
            control: "object",
        },
    },
    args: {
        getConfigFilesDataProvider: () => new Promise((resolve) => setTimeout(() => resolve({ data: articlesFunds }))),
    },
};

export const Default = (args) => ({
    components: { 
        ParentComponent,
        ChildComponent: MockChildComponent // 替换原ChildComponent
    },
    props: Object.keys(args),
    template: `
        <ParentComponent
        :data-provider="getConfigFilesDataProvider"
        />
    `,
});

方法2:通过Webpack别名Mock第三方依赖

如果不想修改Story代码,可以在StoryBook的Webpack配置里,把common-data-provider指向本地的Mock组件:

  1. 修改.storybook/main.js的Webpack配置:
module.exports = {
  // 其他原有配置...
  webpackFinal: async (config) => {
    config.resolve.alias = {
      ...config.resolve.alias,
      // 指向你的Mock DataProvider组件路径
      'common-data-provider': require.resolve('../__mocks__/MockDataProvider.vue')
    };
    return config;
  },
};
  1. 创建__mocks__/MockDataProvider.vue:
<template>
  <div>Mocked Data Provider</div>
</template>

<script>
export default {
  name: 'DataProvider',
  props: ['data'] // 匹配原组件的props
};
</script>

方法3:全局注册Mock组件覆盖动态导入

在StoryBook的预览配置文件(.storybook/preview.js)中全局注册Mock的DataProvider组件,这样ChildComponent会优先使用全局注册的组件,不会触发动态导入:

import Vue from 'vue';
import MockDataProvider from '../__mocks__/MockDataProvider.vue';

// 全局注册,组件名要和原DataProvider一致
Vue.component('DataProvider', MockDataProvider);

内容的提问来源于stack exchange,提问作者yavgz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:10:49