Vue3入门 - 解决pinia判断用户是否登录相关错误

        近期开发Vue3时,计划通过pinia判断用户是否登录,进行相关权限校验时,出现相关错误并对其分析和解决。

一、useStore()错误使用

        通过pinia判断用户是否登录,并在路由卫士beforeEach()方法中进行校验,结果报错:"getActivePinia()" was called but there was no active Pinia.  Are you trying to use a store before calling "app.use(pinia)"?【"getActivePinia()" 被调用时未有实例Pinia。在执行app.use(pinia)之前,尝试使用本地仓库】。

        Pinia存储依赖于Pinia实例来跨所有调用共享相同的存储实例。大多数情况,只需要调用useStore()函数就可以开箱即用。

import { useUsersStore } from '@/stores/user'
import { createPinia } from 'pinia'
import { createApp } from 'vue'
import App from './App.vue'

// ❌  因为它在pinia创建之前调用,所以执行错误
const userStore = useUsersStore()

const pinia = createPinia()
const app = createApp(App)
app.use(pinia)

        确保始终应用此方法的最简单方法是将useStore()的调用放置在安装pinia之后的运行函数中,从而推迟调用。

        此时我们将Vue Router的导航卫士中使用store示例。

错误示例:

import { createRouter } from 'vue-router'
import { useUsersStore } from '@/stores/user'
const router = createRouter({
  // ...
})

// ❌ 根据导入顺序,此方法将执行失败
const store = useUsersStore()

router.beforeEach((to, from, next) => {
  // 使用此方法判断是否登录
  if (store.isLoggedIn) next()
  else if(to.path != '/login') next('/login')
})

        错误示例执行后,会报"getActivePinia()" was called but there was no active Pinia. Are you trying to use a store before calling "app.use(pinia)"?错误。

正确示例:

import { createRouter } from 'vue-router'
import { useUsersStore } from '@/stores/user'
const router = createRouter({
  // ...
})

router.beforeEach((to, from, next) => {
  // ✅ 可以正常执行,因为会在路由器创建后启用它
  // 此时路由器和pinia都已安装
  const store = useUsersStore()

  if (to.meta.requiresAuth && !store.isLoggedIn && to.path != '/login') next('/login')
  else next()
})

二、ts语法错误

        当上述问题解决后,又出现ts语意错误:“Parameter '_token' implicitly has an 'any' type.”【参数'_token'隐式具有'any'类型】。虽然编译通过,但代码上始终显示波浪线,对于有强迫症的,必须将它解决掉。

2.1 useStore()定义

        定义useUsersStore仓库,代码如下:

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useUsersStore = defineStore('counter', () => {
  // 定义属性
  const userInfo = ref(undefined)
  const accessToken = ref('')
  // 计算属性
  const user_info = computed(() => userInfo.value !== undefined && userInfo) // 用户信息
  const access_token = computed(() => accessToken.value && accessToken) //访问令牌
  const is_login = computed(() => userInfo.value != null && accessToken.value) // 校验是否登录属性
  // actions方法
  const updateUserinfo = (_user) => (userInfo.value = _user) // 更新用户令牌
  const updateAccessToken = (_token) => (accessToken.value = _token) //更新访问令牌

  return { user_info, access_token, is_login, updateUserinfo, updateAccessToken }
})

        由于本项目使用的是ts组合开发,所以如下图,可以看到入参位置有波浪线,当错误放上去时,提示的错误为:Parameter '_token' implicitly has an 'any' type.,虽然并不影响编译,但影响代码美观。

2.2 指定泛型

        这里我们使用type来定义自定义类型关键字,它可以表示任何类型。同时,也了解泛型ref<>的使用方法。代码如下:

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
type User = {
  id: number // 用户id
  name: '' //用户姓名
}
export const useUsersStore = defineStore('counter', () => {
  // 定义属性
  const userInfo = ref<User | undefined>(undefined) // 指定其类型为User或undefined,并初始化为undefined
  const accessToken = ref<String>('') //定义其类型为String,并初始化为''
  // 计算属性
  const user_info = computed(() => userInfo.value !== undefined && userInfo) // 用户信息
  const access_token = computed(() => accessToken.value && accessToken) //访问令牌
  const is_login = computed(() => userInfo.value != null && accessToken.value) // 校验是否登录属性
  // actions方法
  const updateUserinfo = (_user: User) => (userInfo.value = _user) // 更新用户令牌,并且入参需要指定类型
  const updateAccessToken = (_token: String) => (accessToken.value = _token) //更新访问令牌,并且入参需要指定类型

  return { user_info, access_token, is_login, updateUserinfo, updateAccessToken }
})

        当指定类型之后,页面中的波浪线则没有了。虽然和Javascript方面有一些差异,但使用Typescript可以弥补Javascript的缺陷,提供更好的开发体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值