当前位置: 首页 > 工具软件 > Vue-SSR > 使用案例 >

vue3项目之VUE-SSR 第二次改造方案

李和昶
2023-12-01

VUE-SSR 第二次改造方案

这次改造方案的目的是让服务端获取到 vuex 里的动态数据,使得在服务端渲染的时候把动态数据也渲染出来

服务端获取到 vuex 里的动态数据之后,再同步到 客户端的 vuex 中。

下面是报错解决:

  • 服务端发送的请求不能是 mockjs 请求!
  • 服务端发送请求不能使用 nprogress 进度条
  • asyncData 只能在路由组件中使用
  • 我的项目 getRoomlist 使用的是 mockjs 接口,所以用的是客户端获取 vuex
  • getCategoryList 真实接口是服务端获取的!(虽然没啥用…)

7.1 改造 entry-server.ts

  • 首先匹配路由组件(无法匹配路由组件中的子组件!!!

  • 每次刷新页面则对匹配的路由组件调用里面的 asyncData 函数(这里如果是路由跳转则不会调用)

  • 导出的 vuex 的数据 state

import { createApp } from './main'
import { renderToString } from 'vue/server-renderer'

export async function render(url: string) {
    const { app, router, store } = createApp()

    await router.push(url)
    await router.isReady()

    // 匹配路由组件
    const matchedComponents = router.currentRoute.value.matched.flatMap(record =>
        Object.values(record.components)
    )

    // 对所有匹配的路由组件调用里面的 asyncData 函数
    await Promise.all(matchedComponents.map(function(Component) {
        if(Component.asyncData) {

            // asyncData 函数接收这些参数
            return Component.asyncData({ store, route: router.currentRoute })
        }
    }))
    
    
    const appHtml = await renderToString(app)
    const state = store.state

    return { appHtml, state }
}

7.2 实现 Vuex 数据同步

服务端获取到 vuex 里的动态数据之后,再同步到 客户端的 vuex 中

  • index.html
<body>
    <div id="app"><!--ssr-outlet--></div>
    <script type="module" src="/src/entry-client.ts"></script>

    <script>
        window.__INITIAL_STATE__ = '<!--vuex-state-->'
    </script>
</body>
  • entry-client.ts

router.beforeEach 函数前加入

if ((window as any).__INITIAL_STATE__) {
    store.replaceState((window as any).__INITIAL_STATE__)
}

7.3 改造 server.js

获取服务端入口文件导出的 vuex 的数据 state ,并和 html 文档一实现替换效果

// 4. 渲染应用的 HTML。这假设 entry-server.js 导出的 `render`
//    函数调用了适当的 SSR 框架 API。
const { appHtml, state } = await render(url)


// 5. 注入渲染后的应用程序 HTML 到模板占位符中(重点!)
const html = template.replace(`<!--ssr-outlet-->`, appHtml)
.replace('\'<!--vuex-state-->\'', JSON.stringify(state))

7.4 asyncData 函数的实现

asyncData 函数会在路由组件服务端渲染的时候被调用

可惜的是使用这个函数就不能使用 setup 语法糖了!!!!

案例:asyncData 函数初始化 vuex 数据,使服务端和客户端同步获取

<script lang="ts">
import { useStore } from '@/store'

export default ({

    setup() {
        const store = useStore()

        let roomList = store.state.categoryList[0]

        return {
            roomList
        }
    },

    async asyncData({ store, route }: any) {
        await store.dispatch('getCategoryList')
    }
})

</script>

<template>
    <div>{{ roomList }}</div>
</template>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YbMhEZmU-1677768515026)(mark-img/image-20230228181131199.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CuzXleR8-1677768515029)(mark-img/image-20230228181208631.png)]

 类似资料: