使用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回答
-
同学你好
经查,在于你的 getters 没有用 computed 啊。 不管是 pinia 还是 vuex,getter 都是要用 computed 包裹的。
// 获取column 用户点击的专栏信息 const column = computed(() => store.getColumn(currentId)) // 获取list 显示该专栏的文章列表 const list = computed(() => store.getPosts(currentId))
修改以后就可以了。亲测有效~
012023-01-08 -
张轩
2023-01-07
同学你好
请问是否可以提供一下代码库,我在本地帮你调试看一下,谢谢
012023-01-07 -
kkdaly
提问者
2023-01-06
排查了下好像是在setup调用pinia的action时,是一个异步的请求,后面的getter会先执行,执行完后获取数据是空的,等待异步请求执行完毕后,页面没有渲染
目前找到了一个解决办法:
使用Suspense组件 + setup语法糖使用 await 让异步变为同步解决了这个问题,不知道老师还有没有其它的解决方法00
相似问题