> 文档中心 > 下一代Vuex(Pinia)不学你就out了

下一代Vuex(Pinia)不学你就out了


为什么说不学Pinia你就out了。

Pinia是下一代Vue状态管理库,在Vue-cli中已经替换了原来的Vuex,且同时支持Vue2.0和Vue3.0两个大版本。Pinia简化了状态管理,抛弃了Vuex中的mutation,只有 state, getteraction ,且完美支持TypeScript及Vue3.0的hooks,可以很好的进行代码分割。

一、安装Pinia

初始化项目: npm init vite@latest

安装Pinia: npm i pinia

import { createApp } from 'vue'import App from './App.vue'// 导入构造函数import { createPinia } from 'pinia'// 创建Vue应用实例appconst app = createApp(App)// 应用以插件形式挂载Pinia实例app.use(createPinia())app.mount('#app')

二、创建全局状态store

// stores/counter.ts// 引入仓库定义函数import { defineStore } from 'pinia'// 传入2个参数,定义仓库并导出// 第一个参数唯一不可重复,字符串类型,作为仓库ID以区分仓库// 第二个参数,以对象形式配置仓库的state,getters,actionsexport const useCounterStore = defineStore('counter', {  // 存储全局状态  state: () => {    return { name: 'hello pinia', count: 0 }  },  // 用来封装计算属性,有缓存功能,类似于computed  getters: {    getName(state) {      return state.name + '...'    }  },  // 处理业务逻辑,对state中的数据进行修改  actions: {    increment() {      this.count++    },    subtract() {      this.count--    }  }})

三、基本示例

一旦仓库被实例化,就可以直接通过实例对象访问仓库上的stategettersactions中定义的任何属性。

<template>  <h1 style="color: blue">{{ store.getName }}</h1>  <h2>数值变化:{{ store.count }}</h2>  <button type="button" @click="store.increment">点击 + 1</button>  <button type="button" @click="store.subtract">点击 - 1</button></template><script setup lang="ts">// 在需要使用状态的组件内需要先导入仓库:import { useCounterStore } from '../stores/counter'// 实例化仓库const store = useCounterStore()</script>

四、数据解构

Pinia中的store是一个用reactive包装的对象,不能直接通过ES6规范进行解构,因为这样做会使状态不具有响应性。

在这里插入图片描述

为了保持状态的响应行,应通过storeToRefsAPI 对仓库实例结构以便获取状态。

<template>  <h1 style="color: blue">name属性示例:{{ name }}</h1>  <h1 style="color: green">getter属性示例:{{ store.getName }}</h1>  <h1>数值变化:{{ count }}</h1>  <button type="button" @click="store.increment">点击 + 1</button>  <button type="button" @click="store.subtract">点击 - 1</button></template><script setup lang="ts">// 在需要使用状态的组件内需要先导入状态仓库:import { storeToRefs } from 'pinia'import { useCounterStore } from '../stores/counter'// 实例化仓库函数const store = useCounterStore()const { name, count } = storeToRefs(store)</script>

五、数据修改

Pinia中数据修改可以一次修改一个状态,也可以一次修改多个状态。

修改单个状态比较简单,不像Vuex每次需要调用Vuex的api,Pinia中,修改单个状态,可直接通过仓库函数的实例直接调用。

如以下示例中修改name值

// stores/name.tsimport { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', {  state: () => {    return { name: 'hello pinia', count: 0 }  },  getters: {    getName(state) {      return state.name + '...'    }  },  actions: {    setName(val: string) {      this.name = val    },    increment() {      this.count++    }  }})
<template>  <h1 style="color: blue">name属性示例:{{ store.name }}</h1>  <h1 style="color: green">getter属性示例:{{ store.getName }}</h1>  <button type="button" @click="store.setName('修改了name')">点击修改name</button></template><script setup lang="ts">import { useCounterStore } from '../stores/counter'const store = useCounterStore()</script>

修改多条状态,Pinia中一次修改多条状态,需要通过官方提供的$patch$patch 方法可以接受的参数类型可以是一个函数也可以是一个对象对象。

<template>  <h1 style="color: blue">count:{{ store.count }}</h1>  <h1 style="color: green">name:{{ store.name }}</h1>  <button type="button" @click="changeState">点击修改store中的状态</button>  <button type="button" @click="changeState2">点击修改store中的状态</button></template><script setup lang="ts">// 在需要使用状态的组件内需要先导入状态仓库:import { useCounterStore } from '../stores/counter'// 实例化仓库函数const store = useCounterStore()const changeState = () => {  store.$patch({    count: 2,    name: '通过$patch的对象形式修改了名称'  })}const changeState2 = () => {  store.$patch(state => {    state.count = 4    state.name = '通过$patch的函数形式修改了名称'  })}</script>

6、多仓库之间的调用

在 Pinia 中,可以在一个 storeimport 另外一个 store ,然后通过调用引入 store 方法的形式,获取引入 store 的状态。
在这里插入图片描述

定义config

// stores/config.tsimport { defineStore } from 'pinia'export const useConfigStore = defineStore('config', {  state: () => {    return {      primaryColor: '#5468ff'    }  },  getters: {},  actions: {}})

定义name

// stores/name.tsimport { defineStore } from 'pinia'import { useConfigStore } from './config'export const useCounterStore = defineStore('counter', {  state: () => {    return { name: 'hello pinia', count: 0 }  },  getters: {    getName(state) {      return state.name + '...'    },     // 调用外部的store    getConfig() {      const config = useConfigStore()      return config.primaryColor    }  },  actions: {    setName(val: string) {      this.name = val    },    increment() {      this.count++    }  }})

应用仓库数据

<template>  <h1 style="color: blue">count:{{ store.count }}</h1>  <h1 style="color: green">name:{{ store.name }}</h1>  <!-- 获取另外一个config中的配置 -->  <h1 style="color: green">name:{{ store.getConfig }}</h1></template><script setup lang="ts">// 在需要使用状态的组件内需要先导入状态仓库:import { useCounterStore } from '../stores/name'// 实例化仓库函数const store = useCounterStore()</script>

Pinia个人感触最深的是对于TypeScript的兼容,无论是在模板语法或者是逻辑处理中,都可以完美的提示仓库上的stategettersactions中定义的任何属性。

7、往期内容已全部收录在专栏中:

Flutter专栏_WEB前端李志杰的博客-CSDN博客

Vue专栏_WEB前端李志杰的博客-CSDN博客