Pinia使用
Pinia与Vuex关系
Pinia 最初是为了探索 Vuex 的下一次迭代会是什么样子,结合了 Vuex 5 核心团队讨论中的许多想法。
安装Pinia
安装
# yarn
yarn add pinia
# 或 npm
npm install pinia
引入(vue3)
main.js
import { createPinia } from 'pinia'
const pinia=createPinia()
app.use(pinia)
//简写
app.use(createPinia())
Store
一个 Store (如 Pinia)是一个实体,它持有未绑定到您的组件树的状态和业务逻辑。。它有三个概念,state、getters 和 actions 并且可以安全地假设这些概念等同于组件中的“data”、“computed”和“methods”。
定义Store
- Store 是使用
defineStore()
定义的 definestore()
的第二个参数可接受两类值: Setup 函数或 Option 对象
import { defineStore } from 'pinia'
// 第一个参数:需是唯一名字,被用作id
// 第二个参数:将返回的函数命名为 use... 是符合组合式函数风格的约定
//Option对象
export const useStore = defineStore('main', {
//相当于data
// 使用函数的方式可以防止数据污染 (针对于服务端),并且具有完整类型推断
state:() => {
return { counter: 5 ,name:'张三',arr:[1,2,3]}
},
//相当于computed
getters:{
gettersCounter(state){
return state.counter++
}
},
actions: {
addCounter(){
this.counter--
}
})
//Setup 函数
export const useCounterStore = defineStore('counterData', ()=>{
//state
const counter=ref(10);
const name=ref('张三');
const arr=reactive([1,2,3]);
//getters
const gettersCounter=computed(()=>{
return counter.value+5;
})
//actions
function addCounter(){
counter.value++;
}
return {counter,name,arr,gettersCounter,addCounter}
})
使用Store
store创建
在 setup()
调用 useCounterStore ()
之前,store 实例是不会被创建的:
import { useCounterStore } from '@/stores/counter!
export default {
setup() {
const store = useCounterStore ()
return {store}
}
}
store响应式
store
是一个用 reactive
包装的对象,像setup
中的 props
一样,不能解构它。
- 使用
storeToRefs()
- 它将为每一个响应式属性创建引用。
- 适用于store
和getters
。
-action
可以直接从store
中解构 ,因为它们也被绑定到store
上:
import { useCounterStore } from '@/stores/counter!
export default {
setup() {
const store = useCounterStore ();
//counter, gettersCounter是响应式
const [ counter, gettersCounter ] = storeToRefs(store);
//action可以直接解构
const { addCounter }= store;
return {counter, gettersCounter,addCounter }
}
}
- 使用
computed
import { useCounterStore } from '@/stores/counter!
export default {
setup() {
const store = useCounterStore ();
//countValue是响应式
const countValue=computed(() => store.count);
return {countValue}
}
}
state
相当于data
状态修改
- 直接修改
store.counter++
- 批量修改 $patch({})
任何集合修改(例如,从数组中推送、删除、拼接元素)都需要您创建一个新集合
store.$patch({
counter:100
name:"李四"
arr:[...store.arr,4]
})
- 批量修改 $patch(()=>{}) 推荐使用
store.$patch((state)=>{
state.counter=100;
state.name="李四";
state.arr.push(4)
})
- 封装在actions中
重置
const store = useStore()
store.$reset()
替换
store.$state = { counter: 1, name: '王五' }
getters
相当于computed
Getters 只是幕后的 computed 属性,无法向它们传递任何参数
可以从 getter 返回一个函数以接受任何参数
getter 不再缓存
书写方式
- 普通函数
getters:{
gettersCounter (state){
return state.counter + 5;
}
// this-->指向store实例 不能对返回值自动推导
gettersCounter (){
return this.counter +5;
}
}
2.箭头函数
getters:{
//无法用this
gettersCounter :(state)=>{
return state.counter + 5;
}
}
调用其他getters
- 调用当前
store
中getters
getters:{
gettersNum :(state)=>{
state.counter++
}
//使用this,不能用箭头函数
gettersCounter (state){
return this.gettersNum + state.counter;
}
}
- 调用其他
store
中getters
getters:{
gettersNum (state)(
const counterStore=useCounterStore();
return state.num+counterStore.gettersCounter;
}
传参
//data为调用时传入参数 和普通函数一样,无缓存作用
gettersCounter (state) {
return (data)=>state.counter + data;
}
actions
相当于 methods
可通过 this 访问整个 store 实例,并支持完整的类型标注(以及自动补全)。
action 可以是异步的。
actions: {
async addCounter(name) {
try {
this.userData = await api.post({ name })
} catch (error) {
// 让表单组件显示错误
return error
}
},
},
调用其他 store
中 actions
actions: {
async changeInfo(name) {
try {
const counterStore=useCounterStore();
const counter= counterStore.addCounter()
if(counter.value==2){
this.userData = await api.post({ name })
}
} catch (error) {
return error
}
},
},