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
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,875评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,569评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,475评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,459评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,537评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,563评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,580评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,326评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,773评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,086评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,252评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,921评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,566评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,190评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,435评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,129评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,125评论 2 352

推荐阅读更多精彩内容