1.1 Pinia介绍
如何实现多个组件之间的数据传递?
-
方式1 组件传参
-
方式2 路由传参
-
方式3 通过pinia状态管理定义共享数据
当我们有
多个组件共享一个共同的状态(数据源)
时,多个视图可能都依赖于同一份状态。来自不同视图的交互也可能需要更改同一份状态。虽然我们的手动状态管理解决方案(props,组件间通信,模块化)在简单的场景中已经足够了,但是在大规模的生产应用中还有很多其他事项需要考虑:
- 更强的团队协作约定
- 与 Vue DevTools 集成,包括时间轴、组件内部审查和时间旅行调试
- 模块热更新 (HMR)
- 服务端渲染支持
Pinia 就是一个实现了上述需求的状态管理库,由 Vue 核心团队维护,对 Vue 2 和 Vue 3 都可用。https://pinia.vuejs.org/zh/introduction.html
1.2 Pinia基本用法
1 准备vite项目
npm create vite
npm install
npm install vue-router@4 --save
2 安装pinia
npm install pinia
3 定义pinia store对象 src/store/store.js [推荐这么命名不是强制]
import {defineStore} from "pinia"
/* 属性介绍:
id: 全局唯一 不能重复
state: { return {数据}} 管理对象的属性
getters: 提前准备一些获取数据的方法
actions: 操作数据的方法
*/
export let userStore = defineStore({
id: "user",
state : () =>{
return {
id: 100,
name: "安琪拉",
gender: "女"
}
},
getters: {
getId(){
return this.id
},
getName(){
return this.name
}
},
actions: {
getMsg(){
return "返回共享数据"
}
}
})
4 在main.js配置pinia组件到vue中
import { createApp } from 'vue'
import './style.css'
import router from "./routers/router"
//导入函数
import {createPinia} from "pinia"
import App from './App.vue'
const app = createApp(App)
//创建pinia对象
const pinia = createPinia()
app.use(router)
//使用pinia
app.use(pinia)
app.mount('#app')
5 UserA.vue 中操作Pinia数据
<script setup>
/* 导入共享数据 */
import {ref,reactive} from "vue"
import {userStore} from "../store/store"
let user = userStore()
</script>
<template>
<div>
<h1>我是UserA数据</h1>
<!-- {{ user }} -->
<div>
ID号: {{ user.id }}<br>
名称: {{ user.name }}<br>
性别: {{ user.gender }}<br>
<hr>
调用id方法: {{ user.getId }}
调用name方法: {{ user.getName }}
<hr>
<!-- 调用赋值方法: -->
{{ user.getMsg()}}
</div>
<div>
<h1>动态赋值</h1>
修改姓名: <input type="text" name="name" v-model="user.name">
</div>
</div>
</template>
<style scoped>
</style>
6 UserB.vue中展示Pinia数据
<script setup>
import {userStore} from "../store/store"
let user = userStore()
</script>
<template>
<div>
<h1>我是UserB数据</h1>
<!-- {{ user }} -->
<div>
ID号: {{ user.id }}<br>
名称: {{ user.name }}<br>
</div>
<div>
<h1>动态赋值</h1>
修改姓名: <input type="text" name="name" v-model="user.name">
</div>
</div>
</template>
<style scoped>
</style>
7 定义组件路由router.js
import {createRouter,createWebHashHistory} from "vue-router"
import UserA from "../components/UserA.vue"
import UserB from "../components/UserB.vue"
const router = createRouter({
history: createWebHashHistory(),
routes: [
{path: "/userA", component: UserA},
{path: "/userB", component: UserB}
]
})
export default router
8 App.vue中通过路由切换组件
<script setup>
</script>
<template>
<div>
<!-- 组件之间数据传递 -->
<router-link to="/userA">跳转到UserA</router-link> <br>
<router-link to="/userB">跳转到UserB</router-link>
<router-view></router-view>
</div>
</template>
<style scoped>
</style>
9 启动测试
npm run dev
1.3 常用属性
- 重置关键字
<button @click="user.$reset()">重置按钮</button>
2.批量修改数据
<button @click="user.$patch({id:200,name:'亚瑟',gender:'男'})">批量修改</button>
1.4 Pinia其他细节
State (状态) 在大多数情况下,state 都是你的 store 的核心。人们通常会先定义能代表他们 APP 的 state。在 Pinia 中,state 被定义为一个返回初始状态的函数。
- store.js
import {defineStore} from 'pinia'
export const definedPerson = defineStore('personPinia',
{
state:()=>{
return {
username:'',
age:0,
hobbies:['唱歌','跳舞']
}
}
)
简化写法
- 简化ID
export let userStore = defineStore("user",{})
3-Getter 完全等同于 store 的 state 的计算值。可以通过
defineStore()
中的getters
属性来定义它们。推荐使用箭头函数,并且它将接收state
作为第一个参数:
export const useStore = defineStore('main', {
state: () => ({
count: 0,
}),
getters: {
doubleCount: (state) => state.count * 2,
},
})
4 Action 相当于组件中的 method。它们可以通过
defineStore()
中的actions
属性来定义,并且它们也是定义业务逻辑的完美选择。类似 getter,action 也可通过this
访问整个 store 实例,并支持完整的类型标注(以及自动补全)。不同的是,action
可以是异步的,你可以在它们里面await
调用任何 API,以及其他 action!
export const useCounterStore = defineStore('main', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++
},
randomizeCounter() {
this.count = Math.round(100 * Math.random())
},
},
})
简化完整代码–了解
import {defineStore} from "pinia"
export let userStore = defineStore("user",{
/* 利用() 简化return */
state : () => ({
id: 100,
name: "安琪拉",
gender: "女"
}),
getters: {
/* 箭头函数没有this 通过参数state 传递数据 */
getId : (state) => state.id,
getName: (state) => state.name
},
actions: {
/* 通过this获取当前对象中的所有数据 */
getMsg(){
console.log(this.id+":"+this.name+":"+this.gender )
return "返回共享数据"
}
}
})
5-监听器用法-在xxx.vue中监控属性变化
<script setup>
/* 导入共享数据 */
import {ref,reactive} from "vue"
import {userStore} from "../store/store"
let user = userStore()
user.$subscribe((mutation,state)=>{
//一般不关心
console.log(mutation)
console.log(state.id + ":" +state.name + ":" + state.gender)
})
</script>