当前位置: 首页 > 知识库问答 >
问题:

如何在Vue 3 SSR应用程序的路由器中使用vuex存储?

慕金林
2023-03-14

我有一个带有SSR、Vue Cli、Vuex和Typescript的Vue3项目。

在路由器页面中,我需要将数据提交到Vuex存储。在一个。vue文件我只是使用这个$在vuex中键入的存储。d、 例如:

this.$store.commit("setFoo", "Bar")

但是如何从没有this或vue实例的ts文件(router/index.ts)中执行此操作呢。

我尝试导入存储索引文件并提交:

import store from "@/store/index"

store.commit("setFoo", "Bar")

但我犯了个错误

类型“”上不存在属性“提交”()=

存储文件(因为我正在运行SSR,所以存储不能是单例):

import Vuex from "vuex"

export default function () {
  return new Vuex.Store({
    state: () => ({
      foo: "foo",
    }),
    mutations: {
      setFoo(state, payload) {
        state.foo = payload
      },
    },
  })
}

更新了vuex 4的存储文件:

import { createStore } from "vuex"

const store = {
  state: () => ({
    foo: "foo",
  })
}

export default function () {
  return createStore(store)
}

输入客户端。js:

import createApp from "./main"

const { app, router } = createApp()

router.isReady().then(() => {
  app.mount("#app", true)
})

entry-server.ts:

import createApp from "./main"

export default function () {
  const { app, router } = createApp()

  return {
    app,
    router,
  }
}

主要的js:

import { createSSRApp, createApp, h } from "vue"
import { isSSR } from "@/helpers"
import createRouter from "@/router"
import createStore from "@/store"
import axios from "axios"
import VueAxios from "vue-axios"
import App from "@/App.vue"

export default function () {

  const rootComponent = {
    render: () => h(App),
    components: { App },
  }

  const app = (isSSR() ? createSSRApp : createApp)(rootComponent)
  const router = createRouter()
  const store = createStore()

  app.use(VueAxios, axios)
  app.use(router)
  app.use(store)

  app.provide("axios", app.config.globalProperties.axios)

  return {
    app,
    router,
    store,
  }
}

路由器/索引。ts:

  import { createRouter, createWebHistory, createMemoryHistory } from "vue-router"
  import store from "@/store/index"
  import axios from "axios"
  import MockAdapter from "axios-mock-adapter"
  import { routes } from "./routes"
  import { isSSR } from "@/helpers"

  const history = isSSR()
    ? createMemoryHistory()
    : createWebHistory(process.env.BASE_URL)

  const router = createRouter({ routes, history })

  router.beforeEach(async (to, from, next) => {
   // do stuff with store
  })
  
  export default function () {
    return router
  }

包裹json:

  "scripts": {
    "build:all": "npm run build:client && npm run build:server",
    "build:client": "vue-cli-service build --dest dist/client",
    "build:server": "export SSR=1 || set SSR=1&& vue-cli-service build --dest dist/server",
    "build:server:dev": "export SSR=1 || set SSR=1&& vue-cli-service build --mode development --dest dist/server",
    "serve:client": "vue-cli-service serve",
    "serve:server": "node ./dist/server/server.js",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "@vue/server-renderer": "^3.2.4",
    "axios": "^0.21.1",
    "core-js": "^3.6.5",
    "express": "^4.17.1",
    "vue": "^3.0.0",
    "vue-axios": "^3.2.5",
    "vue-router": "^4.0.0-0",
    "vuex": "^4.0.0-0"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^4.18.0",
    "@typescript-eslint/parser": "^4.18.0",
    "@vue/cli-plugin-babel": "^5.0.0-beta.3",
    "@vue/cli-plugin-eslint": "^5.0.0-beta.3",
    "@vue/cli-plugin-router": "^5.0.0-beta.3",
    "@vue/cli-plugin-typescript": "^5.0.0-beta.3",
    "@vue/cli-plugin-vuex": "^5.0.0-beta.3",
    "@vue/cli-service": "^5.0.0-beta.3",
    "@vue/compiler-sfc": "^3.0.0",
    "@vue/eslint-config-prettier": "^6.0.0",
    "@vue/eslint-config-typescript": "^7.0.0",
    "axios-mock-adapter": "^1.20.0",
    "eslint": "^7.20.0",
    "eslint-plugin-prettier": "^3.3.1",
    "eslint-plugin-vue": "^7.6.0",
    "node-sass": "^4.12.0",
    "prettier": "^2.2.1",
    "sass-loader": "^8.0.2",
    "typescript": "~4.1.5",
    "webpack-manifest-plugin": "^4.0.2",
    "webpack-node-externals": "^3.0.0"
  }

共有2个答案

叶经略
2023-03-14

默认导出是一个函数

导出默认函数 () {

我想你想这样做:

导出默认的新Vuex。存储({…})

如果你想保留它作为一个函数,你也可以尝试store()。提交,但是每次调用store()都会创建一个新的Vuex实例

陆城
2023-03-14

请注意,避免有状态单例规则不仅适用于主应用程序实例和应用商店,还适用于路由器

当前的路由器/index.ts创建有状态单例。相反,您需要创建一个“路由器工厂”函数,以便每个服务器请求都获得新的路由器实例。额外的好处是,现在您可以将一个商店实例传递给它

路由器/索引。ts

  import { createRouter, createWebHistory, createMemoryHistory } from "vue-router"
  import axios from "axios"
  import MockAdapter from "axios-mock-adapter"
  import { routes } from "./routes"
  import { isSSR } from "@/helpers"

  const createHistory = isSSR()
    ? createMemoryHistory
    : createWebHistory

  export default function (store) {
    const router = createRouter({ 
      routes, 
      history: createHistory(process.env.BASE_URL)
    })

    router.beforeEach(async (to, from, next) => {
      // do stuff with store (store comes from argument)
    })
  
    return router
  }

请注意,服务器和客户端捆绑包都应该使用createSSRApp——如果使用标准createApp,客户端捆绑将不起作用

Vue提供了一个createSSRApp方法,用于在客户端代码中告诉Vue对现有静态HTML进行水合物化处理,而不是重新创建所有DOM元素

main.js

import { createSSRApp, h } from "vue"
import { isSSR } from "@/helpers"
import createRouter from "@/router"
import createStore from "@/store"
import axios from "axios"
import VueAxios from "vue-axios"
import App from "@/App.vue"

export default function () {

  const rootComponent = {
    render: () => h(App),
    components: { App },
  }

  const app = createSSRApp(rootComponent)
  const store = createStore()
  const router = createRouter(store)

  app.use(VueAxios, axios)
  app.use(router)
  app.use(store)

  app.provide("axios", app.config.globalProperties.axios)

  return {
    app,
    router,
    store,
  }
}
 类似资料:
  • 我的任务是创建一个支持typescript的vue3应用程序,我还必须使用vuex进行状态管理,使用vue路由器进行基本路由。但我无法在此项目中使用vue cli 我目前的代码: 由于我从未在vue项目中使用过typescript 您能否向我推荐一些博客、教程,其中有人使用这些工具从头开始构建vue3应用程序,但没有vue cli? 全速行驶: 在VueJS 3.0框架上使用TypeScript编

  • 我尝试了以下示例:从Express.js中删除所有头,在Express node.js中禁用etag头,以及https://github.com/expressjs/Express/issues/2472,但不幸的是,它们没有解决我的问题。在Firefox、Opera和Chrome中,当开发者工具打开并禁用缓存时,或者当我在浏览器上线后第一次启动应用程序时,我的应用程序都能正常工作。我知道这与缓存

  • 我尝试在vuex的操作中使用vue路由器,这在本地主机上运行良好。 然而,当我试图通过从存储文件导入操作来准备存储(模拟)时,我得到了错误。 你能帮我解决这个问题吗? 版本 错误msg app/src/main。js app/src/store/main。js 应用程序/src/路由器/main.js 应用程序/测试/组件/主。测验js 组件

  • 早上好,我正在从事一个vue项目,该项目在应用程序中同时使用vue路由器和vuex。只要登录成功,我就会将JWT令牌存储在vuex中。然而,我对以下几点感到困惑 1) 当路由器中的路由发生变化时,动态显示/隐藏我的导航栏中的登录/注销按钮2)访问vuex存储中的JWT令牌。js 因此,基本上我需要访问路由器中的vuex存储,以及如何在vuex状态更改时(即登录成功时)更新导航栏组件 下面是我的代码

  • 我一直在玩Spring Cloud Stream应用程序启动器中的路由器接收器,我对内容类型有一个问题。 我正在向路由器发送一个JSON字符串,我想编写一个SpEL表达式来确定路由。但是,即使我通过修改项目中的JUnit测试用例来运行它,“有效负载”也会显示为字符串,而不是解析的JSON。当为过滤器处理器运行JUnit测试用例时,也是在Spring Cloud Stream App Starter