vue3 ts setup 监听 pinia 数据的变化,更新页面数据

简述

由于 pinia 导入到vue中的值没有响应性

import useUserStore from './stores/user';
const userStore = useUserStore();
userStore.isvaild;// 没有响应性

那么我们在vue中动态修改某值的想法则需要使用 vue 为我们提供的 watch 方法。Vue3文档

watch([userStore.isvaild, userStore.state.email], ([vaild, email], [prevIsvaild, prevEmail]) => {
/* ... */
})

具体实现

创建和配置Pinia Store

// /stores/user.ts
import { defineStore } from 'pinia';
import { ref, type Ref } from 'vue';
interface UserState {
username: string;
email: string;
}
const useUserStore = defineStore('user', () => {
const state: UserState = {
username: '',
email: ''
};
const isvaild: Ref<boolean> = ref(false);
const setUser = (response: UserState) => {
state.username = response.username;
state.email = response.email;
isvaild.value = true;
};
const getUsername = () => {
return state.username;
};
const getEmail = () => {
return state.email;
};
const logout = () => {
isvaild.value = false;
state.username = '';
state.email = '';
};
return {
isvaild,
state,
setUser,
getUsername,
getEmail,
logout
};
});
export default useUserStore;

在 Vue 组件中监听 Pinia 数据变化

  1. 这是模板内容,脚本内容在第2点
<!-- /App.vue -->
<template>
<div id="app">
<!-- 页眉导航栏 -->
<header>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<!-- 用户登录状态 -->
<div v-if="isLoggedIn">
<HeaderIcon :email="userEmail" />
<button @click="logout">Logout</button>
</div>
<!-- 未登录状态 -->
<div v-else>
<router-link to="/login">Login</router-link>
<router-link to="/forgot-password">Forgot Password</router-link>
</div>
</nav>
</header>
<!-- 页面内容 -->
<main>
<!-- 使用 <router-view> 来呈现不同页面的内容 -->
<router-view></router-view>
</main>
</div>
</template>
<script setup lang="ts">
// ...setup脚本内容
</script>
  1. setup脚本内容
// /App.vue
import { ref, onMounted, watch } from 'vue';
import axios from 'axios';
import { useRouter } from 'vue-router';
import useUserStore from './stores/user';
import HeaderIcon from '@/components/HeaderIcon.vue';
const userStore = useUserStore();
const router = useRouter();
const displayName = ref("");
const userEmail = ref("mcayear@163.com");
const isLoggedIn = ref(userStore.isvaild); // 是否已登录
onMounted(() => {
axios.post(import.meta.env.VITE_SCISERVE + '/api/userinfo', {}, {
headers: { 'Content-Type': 'application/json' },
})
.then((response) => {
if (response.status >= 400 && response.status < 500) {
throw new Error('Client error: ' + response.status);
}
if (response.data.success) {
displayName.value = response.data.data.displayName;
userEmail.value = response.data.data.email;
userStore.setUser(response.data.data);
isLoggedIn.value = true;
router.push('/dashboard');
} else {
// showErrorPopup
console.log(response.data.message);
}
})
.catch((error) => {
// showErrorPopup
console.log(error.toString());
});
});
watch(
() => [userStore.isvaild, userStore.state.email],
([newVaild, newEmail], [oldVaild, oldEmail]) => {
isLoggedIn.value = newVaild as boolean;
userEmail.value = newEmail as string;
}
);
const logout = () => {
isLoggedIn.value = false;
userStore.logout();
axios
.post(import.meta.env.VITE_SCISERVE + '/api/logout', {}, {
headers: { 'Content-Type': 'application/json' },
})
.then(() => {
router.push('/login');
})
.catch((error) => {
// showErrorPopup
console.log(error.toString());
});
};
  1. HeaderIcon.vue 内容
<!-- /components/HeaderIcon.vue -->
<template>
<div>
<img :src="gravatarUrl" alt="Gravatar" />
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { Md5 } from 'ts-md5'; // 详细教程: https://www.cnblogs.com/freejx/p/16934835.html
const props = defineProps({
email: String,
});
// 计算属性,根据邮箱生成Gravatar头像URL
const gravatarUrl = computed(() => {
const hash = Md5.hashStr((props.email|| "").trim().toLowerCase());
return `https://www.gravatar.com/avatar/${hash}?s=100`;
});
</script>
posted @   mcayear  阅读(8722)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示