下一代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应用实例app
const app = createApp(App)
// 应用以插件形式挂载Pinia实例
app.use(createPinia())
app.mount('#app')

二、创建全局状态store

// stores/counter.ts
// 引入仓库定义函数
import { defineStore } from 'pinia'
// 传入2个参数,定义仓库并导出
// 第一个参数唯一不可重复,字符串类型,作为仓库ID以区分仓库
// 第二个参数,以对象形式配置仓库的state,getters,actions
export 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.ts
import { 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.ts
import { defineStore } from 'pinia'
export const useConfigStore = defineStore('config', {
  state: () => {
    return {
      primaryColor: '#5468ff'
    }
  },
  getters: {},
  actions: {}
})

定义name

// stores/name.ts
import { 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博客

  • 12
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一天吃、八顿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值