nuxt3_使用pinia实现服务器端渲染状态管理

安装nuxt3的pinia包

pnpm i pinia @pinia/nuxt
yarn add pinia @pinia/nuxt
npm i pinia @pinia/nuxt

修改nuxt.config.ts的配置

// nuxt.config.ts
export default defineNuxtConfig({
  // ... 其他配置
  modules: [
    // ...
    '@pinia/nuxt',
  ],
})

在项目中创建pinia仓库

// /stores/index.js
import { defineStore } from 'pinia'
export const useRootStore = defineStore('root', {
  state: () => ({
    msg: '测试msg数据',
    articleData: {
      id: undefined,
      title: undefined,
      content: undefined,
    },
  }),
  getters: {},
})

创建本地的测试服务器用于测试ssr

import express from 'express'
import cors from 'cors'
const article = {
  title: 'hello world',
  content:
    'Eu pariatur aliquip enim enim officia laboris proident adipisicing duis aute ex labore nisi excepteur.',
}
const app = express()

app.use(cors())
app.use(express.json())

app.get('/article', cors(), (req, res) => {
  const { id } = req.query
  console.log('访问/article ' + new Date().toString())
  setTimeout(() => {
    res.send({ code: 200, data: { id:Number(id), ...article } })
  }, 1500)
})

app.listen(4520, err => {
  console.log('server is running at port 4520')
})

在nuxt项目中创建服务器端请求接口

// /server/article.get.js
export default defineEventHandler(async event => {
  // console.log(event)
  const { id } = getQuery(event)
  return new Promise(async (resolve, reject) => {
    const res = await $fetch(`http://127.0.0.1:4520/article?id=${id}`).catch(err => err)
    if (res.code === 200) {
      resolve(res)
    } else {
      reject(res)
    }
  })
})

/article/[id]路由页面中实现服务器端渲染

// /pages/article/[id].vue
<template>
  <div id="articleContainer">
    <p>{{ $rootStore?.msg }}</p>
    <p>id:{{ $rootStore?.articleData?.id }}</p>
    <p>标题:{{ $rootStore?.articleData?.title }}</p>
    <p>内容:{{ $rootStore?.articleData?.content }}</p>
  </div>
</template>

<script setup>
import { useRootStore } from '~/stores/index'
const articleStore = useArticleStore()
const $route = useRoute()
const $rootStore = useRootStore()

//#region 初始化数据
initData()
async function initData() {
  const res = await useFetch(`/api/article?id=${$route.params.id}`)
  const res_ = res.data.value
  if (res_.code === 200) {
    $rootStore.$patch({
      articleData: { ...res_.data },
    })
  }
}
//#endregion
</script>

<style scoped lang="scss"></style>

使用postman向http://localhost:3000/article/95发送请求

  • 注释: localhost:3000是nuxt3项目的默认启动地址
  • 得到如下的html结构, 代表服务端渲染成功
<p data-v-inspector="pages/article/[id].vue:3:5">测试msg数据</p>
<p data-v-inspector="pages/article/[id].vue:4:5">id:95</p>
<p data-v-inspector="pages/article/[id].vue:5:5">标题:hello world</p>
<p data-v-inspector="pages/article/[id].vue:6:5">内容:Eu pariatur aliquip enim enim officia laboris proident adipisicing duis aute ex labore nisi excepteur.</p>

修改路由配置实现页面数据缓存

// nuxt.config.ts
  routeRules: {
    '/article/**': { ssr:true },
  },
  • 当路由设置为上面所示时, 每次向/article/[id]路由发起请求都会重新向服务器调用接口,
// 每次刷新页面服务器接口都会打印请求
访问/article Tue Apr 16 2024 13:21:37 GMT+0800 (中国标准时间)
访问/article Tue Apr 16 2024 13:23:28 GMT+0800 (中国标准时间)
访问/article Tue Apr 16 2024 13:23:30 GMT+0800 (中国标准时间)
  • 修改路由配置为
'/article/**': { swr: 60 }, // 页面数据缓存60s, 在缓存数据有效期间不向服务器发起新的请求
  • 修改后, 在60s内无论刷新多少次页面, 服务器接口只会打印一条请求
访问/article Tue Apr 16 2024 13:28:53 GMT+0800 (中国标准时间)
posted @ 2024-04-16 13:31  Syinho  阅读(1028)  评论(0编辑  收藏  举报