Pinia学习总结

389 阅读1分钟

介绍

什么是Pinia

Pinia是vue.js轻量级的状态管理库,类似Vuex,同时支持vue2与vue3。

Pinia的特性

  • 极轻, 仅有 1 KB
  • 清晰、显式的代码拆分
  • 不支持嵌套的模块,通过组合 store 来代替
  • 去掉 mutations,只有 stategetters 和 actions
  • 支持 composition-apioptions-api
  • 更完善的 typescript 支持

使用

安装

yarn add pinia;

引入

import { createApp } from 'vue';
import App from './App.vue';
import { createPinia } from 'pinia';

const app = createApp(App);

const pinia = createPinia();
app.use(pinia);

app.mount('#app');

创建一个store

import { defineStore } from 'pinia';
export const usePerson = defineStore('person', {
  state: () => {
    return {
      name: '李四',
      age: 18,
      merried: false
    }
  },
  getters: {
    info() {
      return `我叫${this.name},今年${this.age}岁,${this.merried ? '已婚' : '未婚'}。`;
    }
  }
})

在组件中使用

<script setup>
import {usePerson} from "../../store/person";
const person = usePerson();
</script>
<p>姓名:{{person.name}}</p>
<p>年龄:{{person.age}}</p>
<p>已婚:{{person.merried}}</p>
<p>自我介绍:{{person.info}}</p>

如果我们想解构 person , 需要使用 storeToRefs 来转成响应式数据。

import { storeToRefs } from "pinia";
const { name, age, merried, info } = storeToRefs(person);

这样就能直接使用 person 里的字段了

<p>姓名:{{name}}</p>
<p>年龄:{{age}}</p>
<p>已婚:{{merried}}</p>
<p>自我介绍:{{info}}</p>

输出内容为:

姓名:李四
年龄:18
已婚:false
自我介绍:我叫李四,今年18岁,未婚。

修改状态数据

直接修改 state 字段

const person = usePerson();
person.age++;
person.merried = true;

最简单的方式。

使用 $patch 传入对象

const person = usePerson();
person.$patch({
  age: 30,
  merried: true
})

适合批量修改多个数据。

使用 $patch 传入函数

const person = usePerson();
person.$patch((state) => {
  state.age++;
  state.merried = state.age > 30 ? true : false;
})

适合处理复杂的数据逻辑。

使用 actions 修改数据

actions: {
  growUp() {
    this.age++;
    this.merried = this.age >= 30 ? true : false;
  }
}

适合处理复杂的数据逻辑,能更好的与组件解耦

使用 $reset 还原数据

person.$reset();

Getters

不带参数

getters类似vue中的computed属性,我们写一个带*号的电话号码

state: () => {
    return {
      phone: 18202810831
    }
 },
getters: {
    phoneHidden(state) {
      return state.phone.toString().replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2');
    }
},

带参数

我们也可以改造一下 phoneHidden 接收一个 isHide 参数。

getters: {
   phoneHidden(state) {
      return (isHide) => {
        if (isHide) {
          return state.phone.toString().replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2');
        } else {
          return state.phone.toString();
        }
      }
    }
},

使用

<p>电话:{{phoneHidden(true)}}</p>
<p>电话:{{phoneHidden(false)}}</p>

输出结果

182****0831
18202810831

store互相调用

我们再创建一个名为 schoolstore

import { defineStore } from "pinia";

export const useSchool = defineStore('school', {
  state: () => {
    return {
      list: []
    }
  },
  actions: {
    addStudent(person) {
      this.list.push(person);
    }
  }
})

然后再给 personactions 添加一个 inSchool 方法

import { useSchool } from './school';
...
actions: {
    inSchool() {
      const school = useSchool();
      school.addStudent(this);
    }
}

调用 inSchool 方法后,school 里面的 list 里面就会多一条数据。 这样我们就实现了store间的调用。

插件

我们添加一个监视器插件,每当有数据修改的时候,告知我们

import { createPinia } from 'pinia';
const pinia = createPinia();

pinia.use(({state}) => {
  store.$subscribe((mutations, state) => {
    console.log('属性修改了', state);
  })
  store.$onAction((action) => {
    console.log(action.name, '方法触发了')
  })
});