搜尋

首頁  >  問答  >  主體

如何在Vue 3 SSR應用中,將vuex store整合到路由器中?

<p>我有一個使用SSR、Vue-Cli、Vuex和Typescript的Vue3專案。 </p> <p>在路由頁面中,我需要將資料提交到Vuex Store。在.vue檔案中,我可以簡單地使用this.$store,它在vuex.d.ts中進行了類型定義,如下:</p> <pre class="brush:php;toolbar:false;">this.$store.commit("setFoo", "Bar")</pre> <p>但是在沒有this或vue實例的ts檔案(router/index.ts)中,我該如何做到這一點呢? </p> <p>我嘗試匯入store索引檔案並進行提交:</p> <pre class="brush:php;toolbar:false;">import store from "@/store/index" store.commit("setFoo", "Bar")</pre> <p>但是我得到了一個錯誤:</p> <blockquote> <p>類型「() => Store<{ foo: string; }>」上不存在屬性「commit」。ts(2339)</p> </blockquote> <p>store檔(由於我正在執行SSR,所以store不能是單例):</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>更新後的vuex 4 store檔:</p> <pre class="brush:php;toolbar:false;">import { createStore } 從 "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>入口伺服器.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>路由器/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 }</前> <p>包.json:</p> <pre class="brush:php;toolbar:false;">"腳本": { "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 --modedevelopment --dest dist/server", "serve:client": "vue-cli-service 服務", “服務:伺服器”:“節點./dist/server/server.js”, "lint": "vue-cli-service lint" }, 「依賴項」:{ "@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” }, 「開發相依性」:{ "@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", “節點-sass”:“^4.12.0”, "更漂亮": "^2.2.1", "sass-loader": "^8.0.2", “打字稿”:“~4.1.5”, "webpack-manifest-plugin": "^4.0.2", “webpack-node-externals”:“^3.0.0” }</pre>
P粉883223328P粉883223328458 天前541

全部回覆(2)我來回復

  • P粉693126115

    P粉6931261152023-08-26 09:40:03

    您的預設導出是一個函數

    export default function () {

    #我認為您想要做的是這樣的:

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

    #如果您想要保持它作為一個函數,您也可以嘗試 store().commit 但這樣每次呼叫 store() 都會建立一個新的 Vuex 實例

    回覆
    0
  • P粉811349112

    P粉8113491122023-08-26 09:19:19

    請注意,避免使用有狀態的單例規則不僅適用於主應用實例和存儲,還適用於路由器

    #您目前的Router/index.ts建立了有狀態的單例。您需要建立一個「路由器工廠」函數,以便每個伺服器請求都獲得新的路由器實例。另一個好處是現在您可以將儲存實例傳遞給它

    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
      }
    

    請注意伺服器和客戶端捆綁包都應使用createSSRApp - 如果使用標準的createApp客戶端的水合作用將無法正常運作

    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,
      }
    }
    

    回覆
    0
  • 取消回覆