How to integrate vuex store into router in Vue 3 SSR application?
P粉883223328
P粉883223328 2023-08-25 10:09:45
0
2
497
<p>I have a Vue3 project using SSR, Vue-Cli, Vuex and Typescript. </p> <p>In the routing page, I need to submit data to the Vuex Store. In the .vue file, I can simply use this.$store, which is type-defined in vuex.d.ts like this: </p> <pre class="brush:php;toolbar:false;">this.$store.commit("setFoo", "Bar")</pre> <p>But how can I do this in a ts file (router/index.ts) without this or vue instance? </p> <p>I tried to import the store index file and submit it: </p> <pre class="brush:php;toolbar:false;">import store from "@/store/index" store.commit("setFoo", "Bar")</pre> <p>But I got an error: </p> <blockquote> <p>Property 'commit' does not exist on type '() => Store<{ foo: string; }>'.ts(2339)</p> </blockquote> <p>store file (since I am running SSR, the store cannot be a singleton): </p> <pre class="brush:php;toolbar:false;">import Vuex from "vuex" export default function () { return new Vuex.Store({ state: () => ({ foo: "foo", }), mutations: { setFoo(state, payload) { state.foo = payload }, }, }) }</pre> <p>Updated vuex 4 store file: </p> <pre class="brush:php;toolbar:false;">import { createStore } from "vuex" const store = { state: () => ({ foo: "foo", }) } export default function () { return createStore(store) }</pre> <p>entry-client.js:</p> <pre class="brush:php;toolbar:false;">import createApp from "./main" const { app, router } = createApp() router.isReady().then(() => { app.mount("#app", true) })</pre> <p>Portal server.ts:</p> <pre class="brush:php;toolbar:false;">import createApp from "./main" export default function () { const { app, router } = createApp() return { app, router, } }</pre> <p>main.js:</p> <pre class="brush:php;toolbar:false;">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, } }</pre> <p>router/index.ts:</p> <pre class="brush:php;toolbar:false;">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 }</pre> <p>包.json:</p> <pre class="brush:php;toolbar:false;">"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" }</pre>
P粉883223328
P粉883223328

reply all(2)
P粉693126115

Your default export is a function

export default function () {

I think what you want to do is this:

export default new Vuex.Store({...})

If you want to keep it as a function, you can also try store().commit but this will create a new Vuex instance every time store() is called

P粉811349112

Please note that Avoid using stateful singletons The rules apply not only to the main application instance and storage, but also to the router

Your current Router/index.ts creates a stateful singleton. You need to create a "router factory" function so that every server request gets a new router instance. Another benefit is that now you can pass a storage instance to it

Router/index.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
  }

Please note that , both server and client bundles should use createSSRApp - if using the standard createApp, Client Hydrationwill not work properly

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,
  }
}
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!