pinia等同于vuex的使用

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 实例

image.png

你可能感兴趣的:(pinia等同于vuex的使用)