NuxtServerInit 在 Vuex 模块模式下不起作用 - Nuxt.js

Posted

技术标签:

【中文标题】NuxtServerInit 在 Vuex 模块模式下不起作用 - Nuxt.js【英文标题】:NuxtServerInit not working on Vuex module mode - Nuxt.js 【发布时间】:2019-07-22 08:53:15 【问题描述】:

NuxtServerInit 在 nuxt js vuex 模块模式下无法处理初始页面渲染。但它适用于经典模式。以下代码是我使用的流程。

我的 api 调用

api/CategoryApi.js

import axios from 'axios';

const HEADERS = 
    Accept: 'application/json'
;

export default 
    getCategory(payload) 
        return axios.get(`$process.env.apiUrl/category`, 
            payload,
            headers: HEADERS
        );
    

store/modules/CategoryStore.js

import api from '~/api/CategoryApi'

const state = () => (
    categories: []
);

const getters = 
    allCategories: state => state.categories
;

const actions = 
    async nuxtServerInit(commit) 
        const payload = 
            per_page: 6,
            page: 1
        ;
        const response = await api.getCategory(payload);
        commit('setCategories', response.data.data);
    ,
;

const mutations = 
    setCategories: (state, data) => 
        state.categories = data;
    
;

export default 
    state,
    getters,
    actions,
    mutations

pages/index.vue

<template>
    <div>
        <v-flex xs6 sm4 md2 class="text-xs-center my-2 pa-2" v-for="category in allCategories" :key="category.id">
             category.name 
        </v-flex>
    </div>
</template>

<script>
    import  mapGetters  from 'vuex';

    export default 
        layout: 'default',
        computed: 
            ...mapGetters(
                allCategories: 'modules/CategoryStore/allCategories',
            )
        ,
    
</script>

我做错了吗? :/ 我想知道实现这一点的正确方法。

编辑:我如何处理 Aldarund 答案(这可能对某人有所帮助)

编辑 store/modules/CategoryStore.js

const actions = 
    async fetchCategories(commit) 
        const payload = 
            per_page: 6,
            page: 1
        ;
        const response = await api.getCategory(payload);
        commit('setCategories', response.data.data);
    ,
;

添加了 store/index.js

const actions = 
    async nuxtServerInit(dispatch) 
        await dispatch('modules/CategoryStore/fetchCategories');
    ,
;

export default 
    actions

【问题讨论】:

【参考方案1】:

如docs中所说

如果你使用的是 Vuex 商店的 Modules 模式,只有主 模块(在 store/index.js 中)将收到此操作。你需要 从那里链接您的模块操作。

所以你需要把你的 nuxtServerInit 放到 store/index.js 中

【讨论】:

你能举个例子说明如何做到这一点。 @Ninja 在文档和示例中。 github.com/nuxt/nuxt.js/blob/… 是的,但我的 Vuex 处于模块模式。所以有点困惑。 @Ninja 我也以模块模式链接的示例 @Aldarund 不确定您的示例是否已更改,但似乎没有处于模块模式?【参考方案2】:

尝试使用该代码,清除文件 index.js,然后在服务器控制台上运行.. 你会看到消息。

     export const actions = 

  nuxtServerInit ( dispatch ) 
    console.log("troololollo")
  

也许也可以试试 nuxt.config.js

module.exports = 
  //mode: 'spa',
  mode: 'universal',

【讨论】:

mode: spa 不会进行 nuxtServerInit 调用。我经过惨痛的教训才学到这个。感谢您的评论。【参考方案3】:

你只能从 store/index.js 中调用 nuxtServerInit 是不对的

我认为最让我困惑的是模块化方法和只有一个存储文件之间的区别。在后一种方法中,我会这样做:

nuxtServerInit(vuexContext, req, redirect, params)
    
      vuexContext.dispatch('someAction',someArguments)
    

而在模块中调用时,例如store/modules/auth.js,你不能使用vuexContext,而是直接使用dispatch:

nuxtServerInit(dispatch)
        
          dispatch('someAction',someArguments)
        

这对我有用,希望对你有帮助

【讨论】:

嘿安德烈,当您只想指出它是代码时,您可以使用“预代码”格式( 图标)而不是可执行的 sn-p 格式( 图标)。 【参考方案4】:

参考文档对这些问题的回答如此之多,但没有人提及如何实际“从 [index.js] 链接您的模块操作。”

posts.js

export const actions = 
  // This isn't called unless it is "chained"
  nuxtServerInit(vuexContext, context) 
    return new Promise((resolve, reject) => 
      // do a thing
      resolve()
    )
  ,

index.js

import  actions as postActions  from './posts' ;

export const actions = 
  nuxtServerInit(vuexContext, context) 
    return new Promise(async (resolve, reject) => 
      // "chain" the desired method
      await postActions.nuxtServerInit(vuexContext, context)
      resolve();
    )
  

【讨论】:

关于异步和等待的新 Promise。 ESLint 实际上并不推荐它。 eslint.org/docs/rules/no-async-promise-executor【参考方案5】:

我在这个问题上花了很多时间。我将尝试在这里用示例代码总结我的发现,以一劳永逸地解决这个问题。

是的,NuxtJS 的文档确实说过,一旦将 Vuex 构建成模块。然后,您的模块的nuxtServerInit 将不会被调用。

除非你在store/index.js触发它。

https://nuxtjs.org/docs/2.x/directory-structure/store#the-nuxtserverinit-action

以前,我们的Vuex结构是这样的。

store/modules/user.js
store/modules/todo.js
store/index.js

因此,您将初始化 index.js 中的模块,并将新模块方式推进到 Vue 3。你仍然需要index.js 来触发你的nuxtServerInit

模块方法的新Vuex结构是这样的。

store/user.js
store/todo.js
store/index.js

是的,您只需将其从您的模块包中取出并移至您的商店包中即可。

现在,让我们从store/index.js 触发todos.nuxtServerInit

'/store/index.js'
import todos from './todos'

const state = () => ()
const getters = 
const mutations = 

const actions = 
  async nuxtServerInit(vuexContext, context) 
    await Promise.all([
        todos.actions.nuxtServerInit(vuexContext, context)
    ])
  ,


export default 
  state,
  getters,
  mutations,
  actions,

现在,在store/todos.js.

'/store/todos.js'

...

const actions = 
  async nuxtServerInit(vuexContext, context) 
    return await vuexContext.commit('todos/setTodos', todos)
  ,


...

如果您以前像vuexContext.commit('setTodos', todos) 一样调用,请记住使用vuexContext.commit('todos/setTodos', todos)

因为现在您的模块位于 store 包中,并且 NuxtJS 已经为您生成了所有包导入。

请注意您的this.$store.getters 是如何进行的,因为它现在也像this.$store.getters['todos/todos'] 一样进行了重组。

【讨论】:

【参考方案6】:

你就不能这样吗……

index.js

export default 
    state: () => (
        context: undefined
    ),

    actions: 
        nuxtServerInit ( state , ctx) 
            state.context = () => ctx;
        
    
;

然后像这样从其他 Store 调用它...

rootState.context().<some object hanging off of the context>

【讨论】:

以上是关于NuxtServerInit 在 Vuex 模块模式下不起作用 - Nuxt.js的主要内容,如果未能解决你的问题,请参考以下文章

nuxtServerInit 与 vuex-module-decorators

nuxt - nuxtServerInit & 页面渲染前的store处理 & context

javascript NUXT - nuxtServerInit

如何修复“超出最大调用堆栈大小”错误

#yyds干货盘点#Vuex实战讲解(全),玩转Vue必备知识

如何在 Vuex 模块中使用 RxJS