vuex的替代方案pinia的使用

目录

1.为什么使用pinia而不再去使用vuex?

2.安装pinia 

3.Store的使用

4.state的使用

5.getters

6.Actions

7.plugins

9.持久化插件pinia-plugin-persistedstate

10.总结


1.为什么使用pinia而不再去使用vuex?

与 Vuex 相比,Pinia 提供了一个更简单的 API,具有更少的规范,提供了 Composition-API 风格的 API,最重要的是,在与 TypeScript 一起使用时具有可靠的类型推断支持。

2.安装pinia 

(pnpm || cnpm || npm) install pinia || yarn add pinia都可以。

vue3引入

import { createPinia } from 'pinia'

app.use(createPinia())

vue2引入

import { createPinia, PiniaVuePlugin } from 'pinia'

Vue.use(PiniaVuePlugin)
const pinia = createPinia()

new Vue({
  el: '#app',
  // 其他选项...
  // ...
  // 注意同一个 `pinia` 实例可以在多个 Vue 应用程序中使用
  // 同一个页面
  pinia,
})

3.Store的使用

首先在src目录下创建一个store文件夹,在这里面放入我们的Store的.js文件。

import { defineStore } from "pinia";
export const useStore = defineStore("main", {});

defineStore定义一个默认的Store,第一个参数是Store的id,第二个参数用来存储Store里面的内容。在组件中使用这个store,首先引入这个js文件,引入它向外暴露的useStore方法,当然这里也可以将存储store的js文件改成默认暴露。

import useStore from "../stores/main";
import { storeToRefs } from "pinia";
export default {
  name: "HelloWorld",
  setup() {
    const store = useStore();
    const { count } = storeToRefs(store);
    setInterval(() => {
      console.log(count);
    }, 5000);
    return {
      store,
      count,
    };
  },
};

我们使用了storeToRefs这个方法来解构数据,将需要转换的store传递进去进行解构。不使用这个方法而去结构赋值,数据的响应式则会失效。

4.state的使用

1.基础使用

const store = useStore();//这个store上面现在有count这个属性
store.count++//我们可以直接访问与修改
store.$reset()会去直接给store中的所有state数据赋值为初始值(重置)

2.mapState方法

computed,methods访问Store,需要调用mapState方法

第一个参数是我们需要使用的store,第二个参数是一个对象,将方法放到其中,每个方法都会去接受传递的store作为参数(只能读取,不能写入), 调用mapState它会将第二个参数对象上面写的方法返回给我们,我们需要通过...解构将返回的方法,放到computed上面。

第二种方法第一个参数不变,第二个参数可以是对象,只不过对象的值不再是函数,而是对应state属性的名字,我们可以重写这个属性的名字,键是重写后的名字,键要重写的属性。

第三种第一个参数和上一个一样,第二个参数变为数组,数组里面是属性名。

import useStore from "../stores/main";
import { mapState } from "pinia";
export default {
  name: "HelloWorld",
  computed: {
    ...mapState(useStore, {
      // myOwnName: "count",
      double: (store) => {
        return store.count * 2;
      },
    }),//第一种写法
   ...mapState(useStore, {
      // myOwnName: "count",
      double:'num'
    }),//第二种写法
    ...mapState(useStore,['num']),//第三种写法
  },
};

3.mapWritableState方法

刚才提到mapState只能读取,无法修改,mapWritableState就解决了这样的问题。

import useStore from "../stores/main";
import { mapWritableState } from "pinia";
export default {
  name: "HelloWorld",
  computed: {
    ...mapWritableState(useStore, ["count", "num"]),
  },
};

我们可以直接在一个input上面去双向绑定数据。

4.改变状态patch

除了直接给store的属性进行赋值以外,我们还可以去调用store上面的$patch方法。

两种写法:

(1)传递一个对象给patch告诉它你要给谁,改谁就去在这个对面上面写上它的属性和值,当你传递的属性值在原来的state上面没有去访问到它会自动给state上面添加上这个属性。

import useStore from "../stores/main";
export default {
  name: "HelloWorld",
  setup() {
    let store = useStore();
    store.$patch({
      count: store.count + 1,
      name: "123",
    });
    console.log(store);
  },
  mounted: function () {},
  computed: {},
};

(2)传递一个函数,参数有当前store的state,可以直接去上面进行添加和修改。

import useStore from "../stores/main";
export default {
  name: "HelloWorld",
  setup() {
    let store = useStore();
    store.$patch((state) => {
      state.count = state.count++;
      state.name = "123";
    });
    console.log(store);
  },
  mounted: function () {},
  computed: {},
};

5.替换state

你甚至可以直接通过store.$state = {} 这样的方式来去修改当前store的state。

pinia.state.value = {}直接将所有的state都赋值为空

6.订阅状态$subscribe

store上面的$subscribe相当于是vue当中的watch,它可以去监听state数据的改变。

    let store = useStore();
    store.$subscribe((mutation, state) => {
      console.log(mutation, state);
    });
    store.$patch((state) => {
      state.count = state.count + 1;
      state.name = "123";
    });

打印的mutation如下:

 events存储发生了什么事件,key代表其改变的属性名.newValue代表新的属性值,oldValue代表旧值,type什么类型,如果这个值是修改为set,给state添加一个新值是add。target代表改变以后得state是什么样子的。

storeId代表当前这个store的id。

type告诉你是通过什么方式改变的,direct直接修改state数据的类型, patch function使用patch修改数据并且传递的是个函数,patch Object传递的是个对象。

(需要注意的是组件销毁的时候监听state的监听也会失效,需要去传递第二个参数{ detached: true })

7.总结pinia的store对比其vuex修改state的数据不再那么麻烦,更加的轻巧便捷。

5.getters

1.基础使用

getter相当于store里面的计算属性。

import { defineStore } from "pinia";
export default defineStore("main", {
  state: () => {
    return {
      count: 123,
      num: 1,
    };
  },
  getters: {
    Bignum: (state) => state.num * 10000,
    Smallcount() {
      console.log(this);
      return this.count - 122;
    },
  },
});

两种写法:

  1. 接收一个当前的state作为参数,将其中的数据返回出去。
  2. 不接收当前的state,直接使用this当前的this指向store。

2.访问其它的getters

Smallcount() {
      return this.Bignum - 10000;
}//this写法
Smallcount(state) {
      return state.Bignum - 10000;
},//接收参数写法

可以通过this去调用其它getters,也可以通过参数来调用。

3.访问其它的store

import { defineStore } from "pinia";
export default defineStore("price", {
  state: () => {
    return {
      carPrice: "100000",
      carNum: 30,
    };
  },
  getters: {
    carTotal(state) {
      return state.carPrice * state.carNum + "¥";
    },
  },
});
import { defineStore } from "pinia";
import price from "./price";//引入刚才的文件
export default defineStore("main", {
  state: () => {
    return {
      count: 123,
      num: 1,
    };
  },
  getters: {
    Bignum: (state) => state.num * 10000,
    Smallcount(state) {
      let priceStore = price()
      return priceStore.carTotal;
    },
  },
});

4.给getters传递参数(给getter传递参数会失去缓存这一特性,你想当于调用的是个方法)

Name() {
  return (name) => "name:" + name;
},//store代码
console.log(store.Name("mike"));//vue文件调用代码

 5.Composition Api setup使用

使用getters与state是一样的,直接store.getter名字即可获取。

6.options Api setup使用

在setup函数中接受store并返回。在computed里面进行接受。

7.vue2的写法

在vue2里面需要使用mapState这一工具函数前面我们在state里面介绍过它,这个函数不仅可以给state使用,getters也可以。

6.Actions

1.默认使用

 actions: {
    setNum() {
      this.num++;
    },
 },//store内容
store.setNum();

action就相当于是store.method,用于修改state中的属性,this默认绑定为当前的store实例。当然在这里面我们是可以去进行异步操作的,当请求的结果需要去修改state中的数据,就将这个方法写到actions里面(推荐这么做,便于管理)。

2.访问其它的store

  actions: {
    setNum() {
      let store = price();
      store.carPrice = "1";
      console.log(store.carPrice);
      this.num++;
    },
  },

price是我引入的别的store文件,我们可以去访问这个store上面的所有属性和方法,我们也可以获取上面的一些属性进行一些判断,比如user存储着用户信息和token,我们需要判断当前有没有token,就会用到,我们还可以再引入的store上面调用patch方法。

3.Composition api setup

import useStore from "../stores/main";
export default {
  name: "HelloWorld",
  setup() {
    let store = useStore();
    return { store };
  },
  mounted: function () {
    console.log(this.a());
  },
  methods: {
    a() {
      this.store.setNum();
    },
  },
};

4.不使用setup

import { mapActions } from "pinia";
import useStore from "../stores/main";
export default {
  name: "HelloWorld",
  mounted: function () {
    console.log(this.setNum());
  },
  methods: {
    ...mapActions(useStore, ["setNum"]),
    ...mapActions(useStore,{a:'setNum'})
  },
};

引入mapActions方法两种传递方式:  

  1. 第一个参数都是需要解构的store,第二个参数可以是一个数组,数组的每一项是一个字符串,为对应store action方法的名字。
  2. 第二种是给第二个参数传递一个对象,可以修改action方法的名字,键为要修改的名字,值为store中的action方法名。

7.plugins

1.基本使用

plugin是一个函数,在main.js里面我们可以在引入createPinia方法后面使用use(plugin函数)来进行使用。

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import { createPinia } from "pinia";
function SecretPiniaPlugin(context) {
  console.log(context);
  return { secret: "the cake is a lie" };
}
const pinia = createPinia();
pinia.use(SecretPiniaPlugin);
createApp(App).use(router).use(pinia).mount("#app");

会自动将这个函数返回对象的值绑定到store上面(后面使用的所有store上面都有secret这个属性),上面的写法就和vue当中的混入差不多。

context参数是个对象有四个属性:

  1. app代表Vue实例。
  2. options代表传递给defineStore的配置对象。
  3. pinia代表当前通过createPinia穿件的pinia实例。
  4. store代表扩展后的store实例。

2.扩展store

你可以使用返回的形式来进行state数据的添加,也可以使用store.属性名的方式添加,不过最好使用返回值,这便于devtools更好的追踪,同时store使用了vue中的reactive这个方法,包裹自身,自动展开各种ref,computeds属性,这也是为什么可以双向绑定这些属性的原因。

3.添加新状态

给store添加初始属性,我们上面已经说过,但给state添加属性的时候,最好使用这种。

function SecretPiniaPlugin({ store }) {
  let num1 = ref("123");
  store.$state.num1 = num1;
  store.num1 = num1;
}

默认使用返回值也只会去在store上面绑定属性,$state访问的还是undefined,在$state上面绑定属性的好处是你可以在vue开发者工具devtools中的pinia选项上面的state观察到,而使用return绑定属性的话会在pinia上面的custom properties上面,使用赋值语句观察不到这个属性。

注:使用了$state就不要使用return再次去返回这个数据,不然的话devtools就会在state部分和custom properties都出现这个属性。

4.添加外部框架属性

当添加外部属性、来自其他库的类实例或仅仅是非响应式的东西时,您应该在将对象传递给 pinia 之前使用 markRaw() 包装对象。 这是一个将路由添加到每个 store 的示例:

import { createApp, ref, toRef, markRaw } from "vue";
import App from "./App.vue";
import router from "./router";
import { createPinia } from "pinia";
function SecretPiniaPlugin({ store }) {
  store.router = markRaw(router);
}
const pinia = createPinia();
pinia.use(SecretPiniaPlugin);
createApp(App).use(router).use(pinia).mount("#app");

 控制台打印正常,但后面all.js抛出了一个错误,控制台还会提示 "storeid" store installed(原因未知)。

5.初始化监听

你也可以在初始化pinia的时候调用store.$subscribe(监听store)和 store.$onAction(监听action)这两个方法。

6.添加新选项

你给defineStore第二个参数传递的所有属性都会被记录到options中,你可以拿这个记录一些信息,你可以率先在初始化store的js里面引入存储用户信息的pinia。然后用到的地方加上一个属性就叫useUserData用true,不用就是没有,true的话在他的state上面加上这个用户信息。

import { defineStore } from "pinia";
export default defineStore("price", {
  state: () => {
    return {
      userInfo:{
         name: "nike",
         age: 10,
         sex: "man",
      }
    };
  },
  getters: {},
});

引入的用户信息如上,使用如下:

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import user from "./stores/user";
import { createPinia } from "pinia";
function SecretPiniaPlugin(context) {
  let data = user().userInfo;
  if (context.options.useUserData) {
    context.store.$state.userData = data;
    context.store.userData = data;
  }
}
const pinia = createPinia();
pinia.use(SecretPiniaPlugin);
createApp(App).use(router).use(pinia).mount("#app");

9.持久化插件pinia-plugin-persistedstate

1.使用

使用npm i pinia-plugin-persistedstate进行下载,然后引入进来。

在main.js使用pinia的后面加上pinia.use( persistedstate)

createApp(App).use(router).use(createPinia().use(persistedstate)).mount("#app");

需要持久化的某个store使用添加配置,传递一个persist为true的属性。

2.配置

  1. persist配置时会变成对象包含下面的属性
  2. key:存储的名字,默认值为当前store的id,可传递一个字符串。
  3. storage:存储方式,默认值为localstorage,可选值localstorage和sessionstorage。
  4. paths:需要持久化的state数据,默认值为undefined,为null或者undefined持久化整个state,可传递字符串类型的数组,包含持久化的state属性。
  5. serializer:持久化时使用的序列型方法,默认读取时JSON.parse,存储时JSON.stringify。 
  6. beforeRestore:在state数据恢复前执行,接收一个参数,这个参数可以可以访问恢复后的数据,可以进行一下用户提示类工作。
  7. afterRestore:在state数据恢复完毕后触发,接收参数同上。
  8. debug:控制恢复store过程发生错误时是否使用console.error打印错误信息,默认为false,也就是不使用。                 

 

10.总结

  1. pinia的灵活性远超于vuex,你可以去双向绑定数据,以及直接对store的数据进行赋值,而不是像vuex一样,一个简单的修改都要写一个Mutation,如果你是一个马虎的人,肯定会在调用的时候敲不对方法名字。
  2. 实现了监听state,action以及相当于vue混入的初始化数据,这都对我们的开发带来了便捷。
  3. 你还在犹豫什么,赶紧用起来。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值