使用pinia改vuex遇到初始化渲染模板为空的情况

来源:7-9 使用 async 和 await 改造异步请求

kkdaly

2023-01-06

老师你好,我尝试着把vuex改成pinia,遇到了一个问题,当页面正常从home页点击 “进入专栏后”,专栏数据和文章数据会正常显示,但是一刷新浏览器数据就会变成空值了,感觉是刷新浏览器后模板直接将state中的数据拿过来渲染,没有等待actions获取完数据再渲染,感觉是生命周期的问题,setup 比mounted先执行,先执行了setup内获取state的方法再运行了mounted内的异步请求,不知道是不是这个原因,请问老师有什么解决办法呢
(使用计算属性是可以正常获取到并显示的,但是使用计算属性后,pinia内的getter就没有用了,没有使用计算属性之前,每次刷新浏览器,getter获取的也是空数据)
图片描述

下面是我的代码

<template>
    <div class="column-detail-page w-75 mx-auto">
      <div class="column-info row mb-4 border-bottom pb-4 align-items-center" v-if="column">
        <div class="col-3 text-center">
          <img :src="column.avatar?.url" :alt="column.title" class="rounded-circle border ">
        </div>
        <div class="col-9">
          <h4>{{column.title}}</h4>
          <p class="text-muted">{{column.description}}</p>
        </div>
      </div>
      <post-list :list="list"></post-list>
    </div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
import PostList from './components/PostList/PostList.vue'
import { useRoute } from 'vue-router'
import useStore from '@/store'
const route = useRoute()
const store = useStore()

const currentId = route.params.id as string

// 获取column 用户点击的专栏信息
const column = store.getColumn(currentId)
// 获取list 显示该专栏的文章列表
const list = store.getPosts(currentId)

onMounted(async () => {
  // 获取点击的专栏数据
  await store.fetchColumn(currentId)
  // 获取当前专栏内的文章数据
  await store.fetchPosts(currentId)
})
</script>

store

const useStore = defineStore('main', {
  state: () => {
    return {
      columns: [] as ColumnProps[],
      posts: [] as PostProps[],
      user: currentUser
    }
  },
  getters: {
    // 根据专栏id获取专栏
    getColumn (state) {
      return (currentId:string) => {
        console.log(state.columns)

        return state.columns.find(c => c._id === currentId)
      }
    },
    // 根据专栏id获取该专栏的文章信息
    getPosts (state) {
      return (currentId:string) => {
        return state.posts.filter(post => post.column === currentId)
      }
    }
  },

  actions: {
    // 添加专栏文章信息
    createPost (newPost:PostProps) {
      this.posts.push(newPost)
    },
    // 获取columns专栏数据
    async fetchColumns () {
      const { data } = await service.get('/columns')
      this.columns = data.data.list
    },
    // 根据专栏id获取专栏数据
    async fetchColumn (cid:string) {
      const { data } = await service.get(`/columns/${cid}`)
      this.columns = [data.data]
    },
    // 获取专栏内的文章数据
    async fetchPosts (cid:string) {
      const { data } = await service.get(`/columns/${cid}/posts`)
      this.posts = data.data.list
    }
  }
})
写回答

3回答

张轩

2023-01-08

同学你好

经查,在于你的 getters 没有用 computed 啊。 不管是 pinia 还是 vuex,getter 都是要用 computed 包裹的。

// 获取column 用户点击的专栏信息
const column = computed(() => store.getColumn(currentId))
// 获取list 显示该专栏的文章列表
const list = computed(() => store.getPosts(currentId))

修改以后就可以了。亲测有效~

0
1
kkdaly
感谢老师!
2023-01-08
共1条回复

张轩

2023-01-07

同学你好

请问是否可以提供一下代码库,我在本地帮你调试看一下,谢谢

0
1
kkdaly
https://github.com/kkdaly/zheye 这个是有问题的代码 在setup_sugar分支下,辛苦老师看看
2023-01-07
共1条回复

kkdaly

提问者

2023-01-06

排查了下好像是在setup调用pinia的action时,是一个异步的请求,后面的getter会先执行,执行完后获取数据是空的,等待异步请求执行完毕后,页面没有渲染
目前找到了一个解决办法:
使用Suspense组件 + setup语法糖使用 await 让异步变为同步解决了这个问题,不知道老师还有没有其它的解决方法
https://img.mukewang.com/szimg/63b827860941436809580662.jpg
https://img.mukewang.com/szimg/63b827ae098a013210801062.jpg
https://img.mukewang.com/szimg/63b8283a0951916606450179.jpg

0
0

Vue3 + TS 仿知乎专栏企业级项目

带你完成前后端分离复杂项目,率先掌握 vue3 造轮子技能

3142 学习 · 2313 问题

查看课程