【问题标题】:Can't read from Vuex store in Storybook无法从 Storybook 中的 Vuex 商店读取
【发布时间】:2020-06-27 20:38:34
【问题描述】:

我正在使用带有 vue create 的 Storybook,我正在尝试从商店读取状态,但我收到以下错误:

Cannot read property 'state' of undefined
TypeError: Cannot read property 'state' of undefined
    at VueComponent.translations (http://localhost:6006/main.08c5b1c8a108e2d2d34c.bundle.js:161:26)
    at Watcher.get (http://localhost:6006/vendors~main.08c5b1c8a108e2d2d34c.bundle.js:86420:25)
    at Watcher.evaluate (http://localhost:6006/vendors~main.08c5b1c8a108e2d2d34c.bundle.js:86525:21)
    at VueComponent.computedGetter [as translations] (http://localhost:6006/vendors~main.08c5b1c8a108e2d2d34c.bundle.js:86775:17)
    at Object.get (http://localhost:6006/vendors~main.08c5b1c8a108e2d2d34c.bundle.js:84041:20)
    at Proxy.render (http://localhost:6006/main.08c5b1c8a108e2d2d34c.bundle.js:895:37)
    at VueComponent.Vue._render (http://localhost:6006/vendors~main.08c5b1c8a108e2d2d34c.bundle.js:85489:22)
    at VueComponent.updateComponent (http://localhost:6006/vendors~main.08c5b1c8a108e2d2d34c.bundle.js:86007:21)
    at Watcher.get (http://localhost:6006/vendors~main.08c5b1c8a108e2d2d34c.bundle.js:86420:25)
    at new Watcher (http://localhost:6006/vendors~main.08c5b1c8a108e2d2d34c.bundle.js:86409:12)

我的HotDescription 组件看起来像:

<template>
    <div class="hot-description">
        <SvgIcon iconId="icon-hot" class="icon-hot"/>
        <span>{{translations.ui.hotMessage}}</span>
    </div>
</template>

<script>

export default {
    name: 'HotDescription',
    computed: {
        translations() {
            return this.$store.state.translations
        }
    }
}
</script>

<style scoped lang="scss">

.hot-description {
    font-size: 14px;
    color: $hot-description-color;
    padding: 2%;
    border-top: 1px solid $hot-description-border-color;
    text-align: center;
}

.icon-hot {
    width: 14px;
    height: 14px;
    margin: 0 3px 3px;
}
</style>

.storybook里面我有两个文件:

main.js:

const path = require('path');

module.exports = {
  stories: ['../stories/**/*.stories.js'],
  addons: ['@storybook/addon-actions', '@storybook/addon-links'],
  webpackFinal: async (config, { configType }) => {
    // `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
    // You can change the configuration based on that.
    // 'PRODUCTION' is used when building the static version of storybook.

    // Make whatever fine-grained changes you need
    config.module.rules.push({
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 
        {
          loader: 'sass-loader',
          options: {
            prependData: `@import "src/project/betpawa/vars.scss"; @import "src/project/common/mixins.scss"; @import "src/styles/styles.scss";`
          }
        }
    ],
      include: path.resolve(__dirname, '../'),
    });

    // Return the altered config
    return config;
  },
};

还有preview.js:

import { configure } from '@storybook/vue';

import Vue from 'vue';
import Vuex from 'vuex';

// Import your global components.
import HotDescription from '../src/components/HotDescription.vue';

// Install Vue plugins.
Vue.use(Vuex);

// Register global components.
Vue.component('HotDescription', HotDescription);

configure(require.context('../stories', true, /\.stories\.js$/), module);

然后是故事 (stories/1-Button.stories.js):

import Test from '../src/components/Test'
import HotDescription from '../src/components/HotDescription'

export default {
    title: 'Button',
    component: Test
}

export const C = () => ({
    components: { HotDescription },
    template: '<HotDescription />'
})

它安装在src/main.js:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import Vuex from 'vuex'

import App from './App'
import router from './router'
import store from './store/store'
import './js/directives'
import './js/plugins'
import './js/globalComponents'
import './js/android'
import './js/filters'
import './js/polyfills'

Vue.config.productionTip = false
Vue.use(Vuex)

const app = new Vue({
    el: '#app',
    store,
    router,
    components: { App },
    template: '<App/>',
    mq: {
        isSmallest: '(max-width: 220px)',
        isVerySmall: '(max-width: 280px)',
        isXXSmall: '(max-width: 340px)',
        isXSmall: '(max-width: 380px)',
        isSmall: '(max-width: 767px)',
        isMedium: '(min-width: 768px)',
        isLarge: '(min-width: 980px)',
        isHighRes: '(-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2)' // , (min-resolution: 192dpi)
    }
})

export default app

任何想法我做错了什么?

Storybook 本身加载,组件在没有状态的情况下工作,这只是需要 vuex 的任何东西都不起作用......

【问题讨论】:

  • 在您的 store/index.js 中将 export const store = 更改为 export default
  • 感谢@ZdravkoPernikov,但这样做仍然会出现同样的错误
  • 你能告诉我们错误吗?
  • 抱歉,已添加!
  • 能否尝试更改导出并重新启动项目?

标签: javascript vue.js vuex storybook


【解决方案1】:

编辑:浏览 Storybook 文档后,我看到 this

您可能正在使用全局组件或 vue 插件,例如 vuex,在这种情况下,您需要在此 preview.js 文件中注册它们

他们的示例代码如下所示:

// Import Vue plugins
import Vuex from 'vuex';

// Install Vue plugins.
Vue.use(Vuex);

您在preview.js 中做过吗? (请记住,我以前从未看过 Storybook,只是浏览文档。)


原答案

商店没有默认导出,因此导入语法不起作用。您可以获取命名的导出:

import { store } from './store'

或者您可以更改商店以使用默认导出:

export default new Vuex.Store({
  state: {
    count: 1
  },
})

【讨论】:

  • 报错说明store没有正确注册。如果您在 main.js 中导入后 console.log(store) 会发生什么?
  • 嗨,丹,不,它没有被放弃。我会在几天后发布更新
  • 没问题。你能显示你安装应用程序并在商店中传递的位置吗?
  • 我不确定 Storybook 是如何安装的——它看起来完全像第二个应用程序——但除非在某个地方将 store 导入其中,否则它将是未定义的。在主应用程序中,可以通过this.$store 从组件访问商店,因为它是通过new Vue 传入的。故事书中应该有类似的东西。
  • 您也可以尝试在HotDescription 内直接使用import store from '@/store/store' 并使用store.state 而不是this.$store.state 访问它。事实上,如果您无法通过 Storybook 的坐骑进入商店,我建议您先尝试一下。唯一的缺点是您必须在使用商店的每个组件中都这样做,这可能没什么大不了的。
【解决方案2】:

仅供参考,我可以通过将以下内容添加到 preview.js 来完成这项工作:

import Vuex from 'vuex';
import Vue from 'vue'
import store from '../src/store/store'

Vue.use(Vuex);
Vue.prototype.$store = store;

【讨论】:

  • 这个 hack 应该是官方文档,效果很好,谢谢伙计
猜你喜欢
  • 2020-01-21
  • 2020-02-05
  • 2018-09-08
  • 2019-11-03
  • 2021-07-12
  • 2019-02-15
  • 1970-01-01
  • 2019-12-20
  • 2020-06-18
相关资源
最近更新 更多