You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

页面重载时调用函数修改状态,Computed状态未更新

问题原因及解决方案

核心原因分析

  1. 路由守卫异步执行时机冲突
    直接访问/notifications时,若isLoggedIn为false,beforeResolve会触发refreshAccessToken异步操作,但组件的<script setup>会在路由守卫的异步操作完成前执行retrieveNotificationList,此时请求携带的是过期token,导致接口请求失败,notifications状态无法更新。而从其他页面跳转时,isLoggedIn已为true,无需刷新token,请求能正常获取数据。

  2. 组件未规范使用Pinia Store实例
    组件中多次调用useStore()(尽管Pinia保证单例),且未在合适的生命周期钩子中执行数据请求,同时retrieveNotificationList未抛出错误,导致请求失败时无法及时排查问题。

  3. 路由守卫顺序错误
    原代码中beforeResolve写在beforeEach之前,不符合Vue Router的执行顺序(正确顺序是beforeEach → beforeResolve → afterEach),可能导致登录校验逻辑执行顺序混乱。

解决方案

1. 调整路由守卫顺序并完善错误处理

// 先执行登录校验的beforeEach
router.beforeEach(async (to, from, next) => {
    if(to.matched.some(record => record.meta.requiresLogin && !isLoggedIn)){
        next({name: 'login'})
    } else{
        next()
    }
})

// 再执行token刷新的beforeResolve
router.beforeResolve((to, from, next) => {
  if (!isLoggedIn) {
    useAuthStore().refreshAccessToken()
    .then(() => {
      // 刷新成功后更新isLoggedIn状态
      isLoggedIn = true
      next()
    })
    .catch(() => {
      // 刷新失败跳转登录页
      next({name: 'login'})
    })
  } else {
    next()
  }
})

2. 规范组件中Store的使用及请求时机

将数据请求放在onMounted钩子中,并复用同一个Store实例,同时处理请求失败的情况:

<template>
        <router-link to="/">Home</router-link> |
    <div :class="{'read':notification.read}" v-for="notification in notifications" :key="notification.id" class="notification">
        <p>{{ notification.message }}</p>
        <button @click="deleteNotification(notification.id)">X</button>
    </div>
</template>

<script setup>
import { useStore } from '../store/index'
import { computed, onMounted } from 'vue'

// 提前获取Store实例,统一复用
const store = useStore()

// 在组件挂载后执行数据请求,确保路由守卫的异步操作已完成
onMounted(async () => {
  try {
    await store.retrieveNotificationList()
  } catch (err) {
    console.error('获取通知列表失败:', err)
    // 可在此处添加错误提示逻辑
  }
})

const notifications = computed(() => {
    return store.notifications
})

function deleteNotification(id) {
    store.deleteNotification(id)
}
</script>

3. 完善Store中action的错误处理

修改retrieveNotificationList,在请求失败时抛出错误,方便组件捕获处理:

export const useStore = defineStore('core', {
    state: () => {
        return {
            notifications: null
        }
    },
    actions: {
        retrieveNotificationList() {
            return new Promise((resolve, reject) => {
                getAPI.get('/api/notifications/')
                .then(response => {
                    this.notifications = response.data
                    resolve()
                })
                .catch(err => {
                    console.error(err)
                    reject(err) // 抛出错误,让调用方可以捕获
                })
            })
        },
        deleteNotification(id) {
            getAPI.delete('/api/notifications/' + id)
                .then(() => this.notifications = this.notifications.filter(item => item.id !== id))
                .catch(err => console.error('删除通知失败:', err))
        }
    }
})

4. 确保请求拦截器使用最新token

检查getAPI的请求拦截器,确保每次请求都携带最新的token(从AuthStore中获取):

// 示例:axios请求拦截器
getAPI.interceptors.request.use(config => {
  const authStore = useAuthStore()
  if (authStore.accessToken) {
    config.headers.Authorization = `Bearer ${authStore.accessToken}`
  }
  return config
})

内容的提问来源于stack exchange,提问作者Deku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 23:20:39