1、首先下载
yarn add pinia
// or
npm install pinia
2、在main.js中进行注册
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
createApp(App).use(createPinia()).mount("#app");
3、跟vuex一样,创建一个store/index.js,进行创建实例,
- defineStore() 第一个参数是个id相当于vuex中的模块命名,这个作用是可在vue调试工具中进行调试,第二个参数是当前的实例
- defineStore() 可以直接写个对象,在对象中有个属性是id,这个是一样的
import { defineStore } from "pinia";
export const useMainStore = defineStore("main", {
});
export const oneStore = defineStore({
id: "one",
});
- state的写法,目前state是一个函数,返回一个对象,跟vue2中的data写法是一样的
1、
state: () => ({
count: 0,
})
2、
state() {
return {
count: 0,
};
},
- pinia中没有mutation这个方法属性,想要修改state中的数据可以在页面中直接修改,也可以通过actions进行修改,actions可以是同步的,也可以是异步的
- 修改state中的数据(声明的实例,一定要实例化下useMainStore())
const store = useMainStore();//todo 第一个store仓库相当于是模块
store.count++ //todo 直接修改state中的数据
store.$patch({ //todo 通过对象的形式,直接修改
count: 2
})
store.$patch((state) => {//todo 返回的回调函数直接进行修改(推荐)
state.count++
})
store.reduceCount();// todo 获取store中的actions
//store中的方法
actions: {
reduceCount() {
//! 只能写普通函数,通过this进行修改state中的数据,不能写箭头函数,this会丢失
return (this.count -= 1);
},
},
- state中的数据都相当于reactive声明的属性,使用解构赋值的话,数据的响应式会消失,可以使用pinia中的
storeToRefs将数据变为响应式的,跟vue中的toRefs一样
import { storeToRefs } from 'pinia';
import { oneStore } from './store/index'
const store1 = oneStore();
let { num, num2 } = storeToRefs(store1);
const add = () => {
store1.num++;
store1.$patch((state)=>state.num++)
}
//store实例
export const oneStore = defineStore({
id: "one",
state: () => ({
num: 2,
num2: 6,
}),
});
- 使用pinia提供的api可以直接重置store实例中的数据
import { useMainStore } from './store/index'
const store = useMainStore();//todo 第一个store仓库相当于是模块
//重置
const reset = () => {
store.$reset(); //todo 直接将仓库中的数据重置
}
- store.$subscribe 这个api是当state中的数据发生变化的时候,可以监听到state中的数据的变化(跟watch差不多),会有返回值,调用返回的这个属性,可以停止监听到state的变化
//todo 订阅, 当state进行发生变化的时候,触发 这个函数
const subscribe = store.$subscribe((mutation, state) => {
// type:type表示这次变化是通过什么产生的,主要有三个分别是
// “direct” :通过 action 变化的
// ”patch object“ :通过 $patch 传递对象的方式改变的
// “patch function” :通过 $patch 传递函数的方式改变的
console.log('第一个参数', mutation)//todo 这个参数相当于是watch,有新老值的 storeId :是当前store的id
console.log(state)
})
- 停止监听state数据的变化
//todo 停止监听 state的变化
const stop = () => {
subscribe();//todo 调用订阅的返回值就可以停止
}
getters计算属性
- 当前的函数是箭头函数,第一个参数是state
- 当前的函数是普通函数,也可以通过this获取到当前的实例,注意:要是使用ts的话,当前的函数要有返回值类型
getters: {
addCount: (state) => {
//! 箭头函数参数为state,普通函数,直接使用this进行修改state中的数据
return (state.count += 7);
},
oneNum(state) {
console.log(state, "================");
return state.num += 1;
},
oneNum(state) {
console.log(this, "================");
return this.num += 1;
},
},
actions 可以是同步,也可以是异步的
- 同步的,我们一般可以直接统一的进行修改state中的数据
- 异步的,我们可以请求接口或者是其他的处理
actions: {
reduceCount() {
//! 只能写普通函数,通过this进行修改state中的数据,不能写箭头函数,this会丢失
return (this.count -= 1);
},
subscribeAction(name, age, manualError) {
return new Promise((resolve, reject) => {
console.log("subscribeAction函数执行");
if (manualError) {
reject("手动报错");
} else {
this.user.name = name;
this.user.age = age;
resolve(`${this.user.name}今年${this.user.age}岁了`);
}
});
},
},
import { useMainStore } from './store/index'
const store = useMainStore();//todo 第一个store仓库相当于是模块
const add = ()=>{ store.subscribeAction('小白', 17, false) }
- store.$onAction()订阅actions,监听actions中的方法每次调用时,发生的变化,返回值调用可停止监听
actions: {
subscribeAction(name, age, manualError) {
return new Promise((resolve, reject) => {
console.log("subscribeAction函数执行");
if (manualError) {
reject("手动报错");
} else {
this.user.name = name;
this.user.age = age;
resolve(`${this.user.name}今年${this.user.age}岁了`);
}
});
},
},
import { useMainStore } from './store/index'
const store = useMainStore();//todo 第一个store仓库相当于是模块
const add = ()=>{ store.subscribeAction('小白', 17, false) }
// todo监听actions中的数据变化
const unsubscribe = store.$onAction(({
name, // action 函数的名称
store, // store 实例,这里是 mainStore
args, // action 函数参数数组(如果是异步的话,就是resolve中的数据)
after, // 钩子函数,在action函数执行完成返回或者resolves后执行
onError, // 钩子函数,在action函数报错或者rejects后执行
}) => {
console.log('action的事件函数名', name)
console.log('参数数组', args)
console.log('store实例', store)
after((result) => {
console.log('$onAction after函数', result)
})
onError(error => {
console.log('错误捕获', error)
})
})
//todo 停止监听actions中的事件
const stopAction = () => {
unsubscribe();
}
- store.$onAction(callback, true),第二个参数为true,来将action订阅和所有组件分开(即组件卸载时,订阅依然有效)
多个命名store之间也可以进行通信
import { defineStore } from "pinia";
export const useMainStore = defineStore("main", {
// state: () => ({
// count: 0,
// }),
state() {
return {
count: 0,
user: {},
};
},
});
export const oneStore = defineStore({
id: "one",
state: () => ({
num: 2,
num2: 6,
}),
getters: {
oneNum(state) {
console.log(this, "================");
return state.num + useMainStore().count; //! useMainStore这个仓库的方法需要调用下,才可以用
},
},
});
pinia支持扩展
- 给store添加新属性,新选项,新方法等
- 添加一个静态方法
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
const store = createPinia();
store.use((context) => {
console.log(context);
context.store.env = "静态属性111";
});
createApp(App).use(store).mount("#app");
const store = useMainStore();//todo 第一个store仓库相当于是模块
console.log('store=========', store.env) 在页面上直接使用就可以了
-
context中有几个属性
app : 当前应用 Vue.createApp() 创建的 app
options : defineStore 配置的数据
pinia : 当前通过 createPinia() 创建的 pinia 实例
store :当前 store 实例