下载
npm i pinia
引入并注册
App.vue
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
// 1. 引入
import { createPinia } from 'pinia'
const app = createApp(App)
// 2. 创建
const pinia = createPinia()
// 3. 注册
app.use(pinia)
app.mount('#app')
存储数据
Store是一个保存 状态、业务逻辑 的实体,每个组件都可以 读取、写入它。
Store有三个概念:state、getter、action,相当于组件中的:data、computed和methods。
首先创建count.ts文件,路径为 src/store/count
使用defineStore定义store,第一个参数为store名,第二个参数为配置对象。
配置对象中的state表示状态,其return的对象中是所有变量,getters可以理解为computed,actions中定义动作函数,函数中可以修改state的值。具体代码如下:
// count.ts
import { defineStore } from 'pinia'
// 定义并暴露一个store
// 命名规范同Hook
export const useCountStore = defineStore('count',{
// 状态
state(){
// 声明变量
return { sum: 6, name: '田本初', age: 23 }
},
// 计算(可以理解为computed)
getters:{
// 可以通过this修改,this就是当前store
addAge():number{
return this.age + 3
},
// 也可以通过参数state修改
doubleSum: state => state.sum * 2
},
// 动作
actions:{}
})
读取、使用数据
state
中定义数据,getters
可以对state中的数据进行计算,并返回一个新数据。
使用数据时有两种方式:「store.变量名」 和 「store.$state.变量名」
第一种更简洁,所以更加推荐第一种写法。
// 读取出定义时暴露出的store
import { useCountStore } from '@store/count'
const countStore = useCountStore()
// 使用state数据
<div>{{ countStore.sum }}</div> // 6
// 或者
<div>{{ countStore.$state.sum }}</div> // 6
// 使用getters数据
<div>{{ countStore.addAge }}</div> // 26
<div>{{ countStore.doubleSum }}</div> // 12
如何简便的使用数据
如下写法过于繁琐,如果只想通过 sum、name、age表达变量,需要将它们解构。
<div>{{ countStore.sum }}</div>
<div>{{ countStore.name }}</div>
<div>{{ countStore.age }}</div>
解构需要注意:由于countStore是响应式数据,不可直接解构使用其中的数据,这会使数据丢失响应式,所以需要使用 toRefs。
<template>
<div>{{ sum }}</div>
<div>{{ name }}</div>
<div>{{ age }}</div>
<div>{{ doubleSum }}</div>
</template>
<script>
import { useCountStore } from '@store/count'
import { toRefs } from 'vue'
const countStore = useCountStore()
// 将countStore中的全部数据变为响应式
const { sum, name, age, doubleSum } = toRefs(countStore)
</script>
但是 toRefs 并不是最好的解决方式
,它会把store中所有值全部变成响应式,如actions函数和一些其他属性。
如果只想修改store中的数据为响应式,需要使用 storeToRefs
。
<template>
<div>{{ sum }}</div>
<div>{{ name }}</div>
<div>{{ age }}</div>
<div>{{ doubleSum }}</div>
</template>
<script>
import { useCountStore } from '@store/count'
// 引入storeToRefs
import { storeToRefs } from 'pinia'
const countStore = useCountStore()
const { sum, name, age, doubleSum } = storeToRefs(countStore)
</script>
修改数据的三种方式
方式一:修改单个数据
不同于Vuex,正如官方文档中说的「Pinia是一个更符合直觉的状态管理工具」,Pinia可以直接修改
store中的数据。
<template>
<div>{{ countStore.sum }}</div>
// 或者
<div>{{ countStore.$state.sum }}</div>
</template>
<script>
import { useCountStore } from '@store/count'
const countStore = useCountStore()
// 比如当前函数直接修改store的state,可以生效
const handler = () => {
countStore.sum += 10
}
</script>
方式二:批量修改数据
语法:store.$patch
({变量名:新值})
<template>
<div>{{ countStore.sum }}</div>
<div>{{ countStore.name }}</div>
<div>{{ countStore.age }}</div>
</template>
<script>
import { useCountStore } from '@store/count'
const countStore = useCountStore()
const handler = () => {
// $patch可以同时修改state中多个数据
countStore.$patch({
sum: 100,
name: '田公路',
age: 24
})
}
</script>
如果多次修改单个数据,会发现进行了多次修改。
如果是批量修改,只进行一次变更,所以需要修改多个数据时,推荐使用$patch进行批量修改。
方式三:通过actions进行修改
需要在store的actions中定义「动作函数」,使用数据的组件中调用该函数,如果进行相对复杂的操作
,并非只修改数据,如:判断以及其他逻辑,更推荐使用actions。
定义actions函数
import { defineStore } from 'pinia'
export const useCountStore = defineStore('count',{
state(){
return { sum: 6, name: '田本初', age: 23 }
},
// 动作
actions:{
// this是当前store
changeName(value){ this.name = value }
}
})
调用函数,修改数据
<template>
<div>{{ countStore.name }}</div>
</template>
<script>
import { useCountStore } from '@store/count'
const countStore = useCountStore()
const handler = () => {
// 直接调用actions中的处理函数,并传入参数
countStore.changeName('田公路')
}
</script>
store.$subscribe
可以理解为watch
,当store中的数据发生了改变,会调用。
它接受一个函数作为参数,该函数有两个参数,分别为mutate和state,mutate是本次修改信息,state是所有数据。
store.$subscribe((mutate,state)=>{
// 处理函数
})
组合式写法(推荐
)
实际开发中更推荐使用组合式写法,Hooks写法。
定义存储数据
import { reactive } from 'vue'
import { defineStore } from 'pinia'
export const useCountStore = defineStore('count',()=>{
// 这里的state同上述写法
const state = reactive({sum: 6, name: '田本初', age: 23})
// changeName相当于在actions中定义的函数
const changeName = value => {
state.name = value
}
// 一定要return
return { state, changeName }
})
读取使用数据
import { useCountStore } from '@/store/count'
import { storeToRefs } from 'pinia'
// 读取
const countStore = useCountStore()
const { sum, name, age } = storeToRefs(countStore)
// 使用
<div>{{ sum }}</div>