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;
  });
};
相关推荐
持续前行28 分钟前
vscode 中找settings.json 配置
前端·javascript·vue.js
JosieBook36 分钟前
【Vue】11 Vue技术——Vue 中的事件处理详解
前端·javascript·vue.js
安逸点39 分钟前
Vue项目中使用xlsx库解析Excel文件
vue.js
一只小阿乐1 小时前
vue 改变查询参数的值
前端·javascript·vue.js·路由·router·网文·未花中文网
小酒星小杜2 小时前
在AI时代下,技术人应该学会构建自己的反Demo地狱系统
前端·vue.js·ai编程
Code知行合壹2 小时前
Pinia入门
vue.js
今天也要晒太阳4732 小时前
element表单和vxe表单联动校验的实现
vue.js
重铸码农荣光2 小时前
TypeScript:JavaScript 的“防坑装甲”,写代码不再靠玄学!
前端·react.js·typescript
南山安2 小时前
TypeScript:更加安全规范的JavaScript
react.js·typescript·代码规范
@PHARAOH3 小时前
WHAT - Vercel react-best-practices 系列(四)
前端·react.js·前端框架