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;
  });
};
相关推荐
码力码力我爱你1 小时前
QT + WebAssembly + Vue环境搭建
vue.js·vue·wasm·webassembly·emscripten
洛千陨1 小时前
element-plus弹窗内分页表格保留勾选项
前端·javascript·vue.js
完球了2 小时前
【Day02-JS+Vue+Ajax】
javascript·vue.js·笔记·学习·ajax
前端没钱2 小时前
若依Nodejs后台、实现90%以上接口,附体验地址、源码、拓展特色功能
前端·javascript·vue.js·node.js
纳尼亚awsl3 小时前
无限滚动组件封装(vue+vant)
前端·javascript·vue.js
八了个戒3 小时前
【TypeScript入坑】TypeScript 的复杂类型「Interface 接口、class类、Enum枚举、Generics泛型、类型断言」
开发语言·前端·javascript·面试·typescript
西瓜本瓜@3 小时前
React + React Image支持图像的各种转换,如圆形、模糊等效果吗?
前端·react.js·前端框架
资深前端之路3 小时前
react jsx
前端·react.js·前端框架
cc蒲公英3 小时前
vue2中使用vue-office库预览pdf /docx/excel文件
前端·vue.js
小兔崽子去哪了4 小时前
Element plus 图片手动上传与回显
前端·javascript·vue.js