如何在 vuex store 中存储 nuxtjs 动态生成的路由
How to store nuxtjs dynamically generated routes in vuex store
我试图通过创建一个静态网站来利用 nuxtjs SSG 功能,其中页面内容和导航是从 API.
中获取的
我已经找到了如何通过定义一个模块来动态生成路由的方法,在该模块中我使用 generate:before
挂钩来获取页面内容和路由。创建路由时,我将页面内容存储为路由负载。以下代码就是这样做的,并且按预期工作。
modules/dynamicRoutesGenerator.js
const generator = function () {
//Before hook to generate our custom routes
this.nuxt.hook('generate:before', async (generator, generatorOptions) => {
generator.generateRoutes(await generateDynamicRoutes())
})
}
let generateDynamicRoutes = async function() {
//...
return routes
}
export default generator
现在我面临的问题是我有一些导航组件需要生成的路线,我想将它们存储到 vuex 商店中。
我尝试了 generate:done
钩子,但我不知道如何从那里获取 vuex 存储上下文。我最终使用的是 nuxtServerInit()
操作,因为如文档中所述:
If nuxt generate is ran, nuxtServerInit will be executed for every dynamic route generated.
这正是我所需要的,所以我尝试将其与以下代码一起使用:
store/index.js
export const actions = {
nuxtServerInit (context, nuxtContext) {
context.commit("dynamicRoutes/addRoute", nuxtContext)
}
}
store/dynamicRoutes.js
export const state = () => ({
navMenuNivel0: {}
})
export const mutations = {
addRoute (state, { ssrContext }) {
//Ignore static generated routes
if (!ssrContext.payload || !ssrContext.payload.entrada) return
//If we match this condition then it's a nivel0 route
if (!ssrContext.payload.navMenuNivel0) {
console.log(JSON.stringify(state.navMenuNivel0, null, 2));
//Store nivel0 route, we could use url only but only _id is guaranteed to be unique
state.navMenuNivel0[ssrContext.payload._id] = {
url: ssrContext.url,
entrada: ssrContext.payload.entrada,
navMenuNivel1: []
}
console.log(JSON.stringify(state.navMenuNivel0, null, 2));
//Nivel1 route
} else {
//...
}
}
}
export const getters = {
navMenuNivel0: state => state.navMenuNivel0
}
确实调用了操作,我得到了所有预期值,但是似乎每次调用 nuxtServerInit()
时,商店状态都会重置。我在控制台中打印了这些值(因为我不确定是否可以调试它)它们看起来像这样:
{}
{
"5fc2f4f15a691a0fe8d6d7e5": {
"url": "/A",
"entrada": "A",
"navMenuNivel1": []
}
}
{}
{
"5fc2f5115a691a0fe8d6d7e6": {
"url": "/B",
"entrada": "B",
"navMenuNivel1": []
}
}
我已经尽我所能搜索了这个主题,虽然我没有找到与我的相似的例子,但我把所有我能找到的部分放在一起,这就是我想出的。
我的想法是只向 API 发出一个请求(在构建期间),将所有内容存储在 vuex 中,然后在组件和页面中使用该数据。
要么有更好的方法,要么我没有完全掌握 nuxtServerInit()
操作。我被卡住了,不知道如何解决这个问题,也看不到其他解决方案。
如果你能做到这一点,感谢你的宝贵时间!
我想出了一个解决方案,但我觉得它不是很优雅。
想法是将API请求数据存储在一个静态文件中。然后创建一个插件来拥有一个公开 API 数据和一些函数的 $staticAPI
对象。
我使用了 build:before
挂钩,因为它在 generate:before
和 builder:extendPlugins
之前运行,这意味着在路由生成或插件创建发生时,我们已经有了 API 数据已存储。
dynamicRoutesGenerator.js
const generator = function () {
//Add hook before build to create our static API files
this.nuxt.hook('build:before', async (plugins) => {
//Fetch the routes and pages from API
let navMenuRoutes = await APIService.fetchQuery(QueryService.navMenuRoutesQuery())
let pages = await APIService.fetchQuery(QueryService.paginasQuery())
//Cache the queries results into staticAPI file
APIService.saveStaticAPIData("navMenuRoutes", navMenuRoutes)
APIService.saveStaticAPIData("pages", pages)
})
//Before hook to generate our custom routes
this.nuxt.hook('generate:before', async (generator, generatorOptions) => {
console.log('generate:before')
generator.generateRoutes(await generateDynamicRoutes())
})
}
//Here I can't find a way to access via $staticAPI
let generateDynamicRoutes = async function() {
let navMenuRoutes = APIService.getStaticAPIData("navMenuRoutes")
//...
}
插件staticAPI.js
:
import APIService from '../services/APIService'
let fetchPage = function(fetchUrl) {
return this.pages.find(p => { return p.url === fetchUrl})
}
export default async (context, inject) => {
//Get routes and files from the files
let navMenuRoutes = APIService.getStaticAPIData("navMenuRoutes")
let pages = APIService.getStaticAPIData("pages")
//Put the objects and functions in the $staticAPI property
inject ('staticAPI', { navMenuRoutes, pages, fetchPage })
}
将 save/load 数据写入文件的 API 服务助手:
//...
let fs = require('fs');
let saveStaticAPIData = function (fileName = 'test', fileContent = '{}') {
fs.writeFileSync("./static-api-data/" + fileName + ".json", JSON.stringify(fileContent, null, 2));
}
let getStaticAPIData = function (fileName = '{}') {
let staticData = {};
try {
staticData = require("../static-api-data/" + fileName + ".json");
} catch (ex) {}
return staticData;
}
module.exports = { fetchQuery, apiUrl, saveStaticAPIData, getStaticAPIData }
nuxt.config.js
build: {
//Enable 'fs' module
extend (config, { isDev, isClient }) {
config.node = { fs: 'empty' }
}
},
plugins: [
{ src: '~/plugins/staticAPI.js', mode: 'server' }
],
buildModules: [
'@nuxtjs/style-resources',
'@/modules/staticAPIGenerator',
'@/modules/dynamicRoutesGenerator'
]
我试图通过创建一个静态网站来利用 nuxtjs SSG 功能,其中页面内容和导航是从 API.
中获取的我已经找到了如何通过定义一个模块来动态生成路由的方法,在该模块中我使用 generate:before
挂钩来获取页面内容和路由。创建路由时,我将页面内容存储为路由负载。以下代码就是这样做的,并且按预期工作。
modules/dynamicRoutesGenerator.js
const generator = function () {
//Before hook to generate our custom routes
this.nuxt.hook('generate:before', async (generator, generatorOptions) => {
generator.generateRoutes(await generateDynamicRoutes())
})
}
let generateDynamicRoutes = async function() {
//...
return routes
}
export default generator
现在我面临的问题是我有一些导航组件需要生成的路线,我想将它们存储到 vuex 商店中。
我尝试了 generate:done
钩子,但我不知道如何从那里获取 vuex 存储上下文。我最终使用的是 nuxtServerInit()
操作,因为如文档中所述:
If nuxt generate is ran, nuxtServerInit will be executed for every dynamic route generated.
这正是我所需要的,所以我尝试将其与以下代码一起使用:
store/index.js
export const actions = {
nuxtServerInit (context, nuxtContext) {
context.commit("dynamicRoutes/addRoute", nuxtContext)
}
}
store/dynamicRoutes.js
export const state = () => ({
navMenuNivel0: {}
})
export const mutations = {
addRoute (state, { ssrContext }) {
//Ignore static generated routes
if (!ssrContext.payload || !ssrContext.payload.entrada) return
//If we match this condition then it's a nivel0 route
if (!ssrContext.payload.navMenuNivel0) {
console.log(JSON.stringify(state.navMenuNivel0, null, 2));
//Store nivel0 route, we could use url only but only _id is guaranteed to be unique
state.navMenuNivel0[ssrContext.payload._id] = {
url: ssrContext.url,
entrada: ssrContext.payload.entrada,
navMenuNivel1: []
}
console.log(JSON.stringify(state.navMenuNivel0, null, 2));
//Nivel1 route
} else {
//...
}
}
}
export const getters = {
navMenuNivel0: state => state.navMenuNivel0
}
确实调用了操作,我得到了所有预期值,但是似乎每次调用 nuxtServerInit()
时,商店状态都会重置。我在控制台中打印了这些值(因为我不确定是否可以调试它)它们看起来像这样:
{}
{
"5fc2f4f15a691a0fe8d6d7e5": {
"url": "/A",
"entrada": "A",
"navMenuNivel1": []
}
}
{}
{
"5fc2f5115a691a0fe8d6d7e6": {
"url": "/B",
"entrada": "B",
"navMenuNivel1": []
}
}
我已经尽我所能搜索了这个主题,虽然我没有找到与我的相似的例子,但我把所有我能找到的部分放在一起,这就是我想出的。
我的想法是只向 API 发出一个请求(在构建期间),将所有内容存储在 vuex 中,然后在组件和页面中使用该数据。
要么有更好的方法,要么我没有完全掌握 nuxtServerInit()
操作。我被卡住了,不知道如何解决这个问题,也看不到其他解决方案。
如果你能做到这一点,感谢你的宝贵时间!
我想出了一个解决方案,但我觉得它不是很优雅。
想法是将API请求数据存储在一个静态文件中。然后创建一个插件来拥有一个公开 API 数据和一些函数的 $staticAPI
对象。
我使用了 build:before
挂钩,因为它在 generate:before
和 builder:extendPlugins
之前运行,这意味着在路由生成或插件创建发生时,我们已经有了 API 数据已存储。
dynamicRoutesGenerator.js
const generator = function () {
//Add hook before build to create our static API files
this.nuxt.hook('build:before', async (plugins) => {
//Fetch the routes and pages from API
let navMenuRoutes = await APIService.fetchQuery(QueryService.navMenuRoutesQuery())
let pages = await APIService.fetchQuery(QueryService.paginasQuery())
//Cache the queries results into staticAPI file
APIService.saveStaticAPIData("navMenuRoutes", navMenuRoutes)
APIService.saveStaticAPIData("pages", pages)
})
//Before hook to generate our custom routes
this.nuxt.hook('generate:before', async (generator, generatorOptions) => {
console.log('generate:before')
generator.generateRoutes(await generateDynamicRoutes())
})
}
//Here I can't find a way to access via $staticAPI
let generateDynamicRoutes = async function() {
let navMenuRoutes = APIService.getStaticAPIData("navMenuRoutes")
//...
}
插件staticAPI.js
:
import APIService from '../services/APIService'
let fetchPage = function(fetchUrl) {
return this.pages.find(p => { return p.url === fetchUrl})
}
export default async (context, inject) => {
//Get routes and files from the files
let navMenuRoutes = APIService.getStaticAPIData("navMenuRoutes")
let pages = APIService.getStaticAPIData("pages")
//Put the objects and functions in the $staticAPI property
inject ('staticAPI', { navMenuRoutes, pages, fetchPage })
}
将 save/load 数据写入文件的 API 服务助手:
//...
let fs = require('fs');
let saveStaticAPIData = function (fileName = 'test', fileContent = '{}') {
fs.writeFileSync("./static-api-data/" + fileName + ".json", JSON.stringify(fileContent, null, 2));
}
let getStaticAPIData = function (fileName = '{}') {
let staticData = {};
try {
staticData = require("../static-api-data/" + fileName + ".json");
} catch (ex) {}
return staticData;
}
module.exports = { fetchQuery, apiUrl, saveStaticAPIData, getStaticAPIData }
nuxt.config.js
build: {
//Enable 'fs' module
extend (config, { isDev, isClient }) {
config.node = { fs: 'empty' }
}
},
plugins: [
{ src: '~/plugins/staticAPI.js', mode: 'server' }
],
buildModules: [
'@nuxtjs/style-resources',
'@/modules/staticAPIGenerator',
'@/modules/dynamicRoutesGenerator'
]