Vue3(ts)中使用 pinia

什么是pinia?

Pinia 最初是在 2019 年 11 月左右重新设计使用 Composition API,可以理解为下一代 vuex,作者也称之为vuex5,同时vue已经将 pinia 收入 官方账户了

名字的由来

Pinia (发音为 /piːnjʌ/,类似英文中的 "peenya") 是最接近有效包名 piña (西班牙语中的 pineapple,即"菠萝") 的词。 菠萝花实际上是一组各自独立的花朵,它们结合在一起,由此形成一个多重的水果。 与 Store 类似,每一个都是独立诞生的,但最终它们都是相互联系的。 它(菠萝)也是一种原产于南美洲的美味热带水果。

为什么要用它?比vuex 强在哪里

pinia 最开始是一个实验,其目的是设计一个拥有组合式 API 的 Vue 状态管理库,来弥补vuex 的不足,且同时满足 vue2和vue3,下图是 pinia作者 总结的五点

  • 1 同时支持 options(vue2)和composition api(vue3)
  • 2 仅保留 state getters actions(取消了vuex 中 Mutation)
  • 3 取消嵌套模块(取消了vuex 中 Module)
  • 4 支持ts
  • 5 透明 自动化的代码拆分

实际应用

项目创建 vite + vue3 + pinia

执行命令 npm create vite@latest 或 yarn create vite

sql 复制代码
yarn create vite
// 或者npm create vite@latest  

按照提示 输入项目名称、框架类型(必须是vue,因为pinia 只支持vue)、TypeScript

安装 pinia

csharp 复制代码
yarn add pinia

挂载

打开main.ts

javascript 复制代码
import { createPinia } from 'pinia'

const pinia = createPinia()

const app = createApp(App)

app.use(pinia)

初始化 定义 Store

src 目录下 创建 index.ts

写法一 类似于 vuex的写法 没有mutations

user为容器(可以理解为命名空间)

javascript 复制代码
import { defineStore } from 'pinia'

export const userStore = defineStore('user', {
  state: () => {
    return {
      name: 'iwhao',
      age: 18,
      count: 1,
    }
  },
  getters: {
    countDouble: (state) => {
      return state.count * 2
    }
  },
  actions: {
    countAdd() {
      this.count++
    }
  }
})

写法二 composition api pinia 会自动识别 ref类型的 为 state 、computed类型的为 getter、function 为 action

javascript 复制代码
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const userStore = defineStore('user', () => {
  const name = ref('iwhao')
  const age = ref(18)
  const count = ref(1)
  const countDouble = computed(() => count.value * 2)
  function countAdd() {
    count.value++
  }
  return { name, age, count, countDouble, countAdd }
})

使用

引用

这里直接在项目中components下的HelloWorld.vue 中写入案列

xml 复制代码
<template>
  <p>name: {{ user.name }}</p>
  <p>age: {{ user.age }}</p>
  <p>count: {{ user.count }}</p>
  <p>countDouble: {{ user.countDouble }}</p>
  <button @click="user.countAdd()">增加</button>
</template>
<script setup lang="ts">
    import { userStore } from "../store/index";
    const user = userStore();
</script>

效果如下

注意

不要直接解构使用,例如下方代码,因为这种写法 name, age, count, countDouble 将不会是响应式

css 复制代码
...
    <p>name: {{ user.name }}</p>
    <p>age: {{ user.age }}</p>
    <p>count: {{ user.count }}</p>
    <p>countDouble: {{ user.countDouble }}</p>
    <button @click="user.countAdd()">增加</button>
    <br />
    <p>name: {{ name }}</p>
    <p>age: {{ age }}</p>
    <p>count: {{ count }}</p>
    <p>countDouble: {{ countDouble }}</p>
    <button @click="user.countAdd()">增加</button>
...
const user = userStore();
const { name, age, count, countDouble } = user;

那如何让解构出来的变量 变成响应式呢,需要引入 storeToRefs

javascript 复制代码
import { storeToRefs } from "pinia";

const { name, age, count, countDouble } = storeToRefs(user);

更新

第一种方法(不推荐,如果只是单变量更新的话无所谓)

ini 复制代码
...
 <button @click="upUser">更新</button>
...
const upUser = () => {
  user.name = '张三'
  user.age = 20
  user.count = 100
}

如果批量更新多个,推荐使用 $patch

ini 复制代码
...
  <button @click="upUserBath">批量更新</button>
...
const upUserBath = () => {
  user.$patch({
    name: "张三",
    age: 20,
    count: 100,
  });
};
// 或 这种写法
const upUserBath = () => {
  user.$patch((state) => {
    state.name = "张三";
    state.age = 20;
    state.count = 100;
  });
};
相关推荐
娃哈哈哈哈呀2 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
yg_小小程序员3 小时前
vue3中使用vuedraggable实现拖拽
typescript·vue
高山我梦口香糖5 小时前
[react 3种方法] 获取ant组件ref用ts如何定义?
typescript·react
真滴book理喻5 小时前
Vue(四)
前端·javascript·vue.js
不是鱼7 小时前
构建React基础及理解与Vue的区别
前端·vue.js·react.js
prall7 小时前
实战小技巧:下划线转驼峰篇
前端·typescript
开心工作室_kaic7 小时前
springboot476基于vue篮球联盟管理系统(论文+源码)_kaic
前端·javascript·vue.js
川石教育7 小时前
Vue前端开发-缓存优化
前端·javascript·vue.js·缓存·前端框架·vue·数据缓存
搏博7 小时前
使用Vue创建前后端分离项目的过程(前端部分)
前端·javascript·vue.js
isSamle7 小时前
使用Vue+Django开发的旅游路书应用
前端·vue.js·django