应用系统定制开发Pinia的使用(在Vue3和TypeScript的环境下)

官网: https://pinia.vuejs.org/

Pinia的使用(在和TypeScript的环境下

1. 创建项目

1.1 应用系统定制开发脚手架搭建

npm init vite@latest

应用系统定制开发后面操作见图示

1.2 安装pinia

该笔记, pinia基于版本2.0.11

npm i pinia@2.0.11 或者 yarn add pinia@2.0.11



2. Pinia - Store

2.1 创建Store

应用系统定制开发在入口文件main.ts中:

import { createApp } from "vue";import App from "./App.vue";// 引入piniaimport { createPinia } from "pinia";// 创建 Pinia 实例const pinia = createPinia();const app = createApp(App);// 挂载到 Vue 根实例app.use(pinia);app.mount("#app");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2.2 Store详讲

在src下, 应用系统定制开发新建文件夹store, 再新建index.ts

在index.ts中:

/** * 应用系统定制开发一般在容器中做这4件事 *    1. 应用系统定制开发定义容器并导出 *    2. 使用容器中的state *    3. 修改容器中的state *    4. 使用容器中的action */import { defineStore } from "pinia";/** * 1. 定义容器并导出 * 参数一: 容器ID, 唯一, 将来 Pinia 会把所有的容器挂载到根容器 * 参数二: 选项对象 * 返回值: 函数, 调用的时候要空参调用, 返回容器实例 */export const mainStore = defineStore('main', {    /**     * 类似组件的 data, 用于存储全局的的状态     * 注意:     *    1.必须是函数, 为了在服务端渲染的时候避免交叉请求导致的数据交叉污染     *    2.必须是箭头函数, 为了更好的 TS 类型推导     */    state: () => {        return {            count: 100,          	foo: 'bar',          	age: 18        }    },    /**     * 类似组件的 computed, 用来封装计算属性, 具有缓存特性     */    getters: {    },    /**     * 类似组件的 methods, 封装业务逻辑, 修改state     * 注意: 里面的函数不能定义成箭头函数(函数体中会用到this)     */    actions: {    }})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

2.3 使用store中的状态

2.3.1 简单访问store状态

components/HelloWorld.vue中的代码清空, 加入以下代码

<template>  <div v-text="mainStoreI.count"></div></template><script lang="ts" setup>  import {mainStore} from '../store'  const mainStoreI = mainStore()  console.log(mainStoreI.count);</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10


2.3.2 访问及简单修改store(标准操作)

但是上面的访问未免过于麻烦, 使用 count、foo 前面还要加 mainStoreI , 如果直接采用解构的方式, 会导致数据不是响应式的, 具体解决方式如下:

import { storeToRefs } from ‘pinia’;

<template>  <div v-text="mainStoreI.count"></div>  <hr>  <p>count: {{ count }}</p>  <p>foo: {{ foo }}</p>  <p>age: {{ age }}</p>  <button @click="handleClick">修改count数据</button></template><script lang="ts" setup>  import {mainStore} from '../store'  import { storeToRefs } from 'pinia';  const mainStoreI = mainStore()  const {count, foo, age} = storeToRefs(mainStoreI)    /** 修改store中的数据 */  const handleClick = () => {    // 修改单个数据,方式一    // count.value++    // 修改单个数据,方式二    mainStoreI.count++  }</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

2.4 store - $patch 批量简单修改

  • 多个数据修改,建议使用 $patch 批量更新,

  • 不单纯是写法优化,还有性能的优化

  /** 修改store中的数据 */  const handleClick = () => {    // 哪些数据项需要修改就写数据项    mainStoreI.$patch({      count: ++mainStoreI.count,      foo: 'hello',    })  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.5 $patch怎么更新数组?

方式一: 利用ES6展开运算符

const handleClick = () => {  mainStoreI.$patch({    // 更新数组    arr: [...mainStoreI.arr, 4]  })}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

方式二: $patch可以接收一个函数(推荐)

const handleClick = () => {  // 给$patch传入一个函数,函数体中修改数据项  // 形参state即为容器  mainStoreI.$patch((state) = {    state.count++;    state.foo = 'hello';    state.arr.push(4)  })}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.6 总结: 修改状态数据的四种方式



3. Pinia - actions

  • 修改 Store 状态时, 如果逻辑较多, 可以借助 actions
  • actions 中也可以使用 $patch, 见下面代码

注意:

  • actions 中的函数, 不能定义成箭头函数
  • 因为箭头函数中没有this, 在运行时, 会向外部的作用域找

src\store\index.ts

/** * 类似组件的 methods, 封装业务逻辑, 修改state */actions: {    changeState(num: number): void {        // this访问当前容器的实例        this.count += num        this.foo='你好啊'        this.arr.push(555)              // 这里也可以使用$patch        // this.$patch({})        // this.$patch(state => {})    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

业务代码<script>中:

/** 修改store中的数据 */const handleClick = () => {    	// 当逻辑较多时,可以封装到actions中处理  	mainStoreI.changeState(10)}
  • 1
  • 2
  • 3
  • 4
  • 5


4. Pinia - getters

  • 具有缓存特性

  • getters的定义有两种

    1. 接受一个形参, 代表容器状态实例(数据)

      count10 (state) {  state.count + 10}
      • 1
    2. 不使用形参, 函数体中使用this, 必须手动指定返回值类型

      原因: 无法推导this的类型, 会导致编译报错, 需手动指定返回值类型

      count10 (): number {  	this.count + 10}
      • 1
      • 2
      • 3
    3. (不推荐) 既使用state, 也使用this, 这个时候可以不手动指定返回值类型

      这种写法怪怪的, 写了形参不用

      count10 (state){  	this.count + 10}
      • 1
      • 2
      • 3

定义:

export const mainStore = defineStore('main', {    	state: () => {        		return {            			count: 100,            			foo: 'bar',            			age: 18,            			arr:[99, 55]        	}    },     /**       * 类似组件的 computed, 用来封装计算属性, 具有缓存特性       */    	  getters: {         	// 每次使用的 count10 都是在 count 的基础上加10          	count10 (state) {              		console.log('count10 调用了');              		return state.count+10          	}      }})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

如图, count10 访问了3次, 但是由于缓存, 实际 getters 只运行了一次:



5. Store相互调用

如果存在相互调用的情况, 和在业务组件中使用一致

  • 在A中导入B
  • 实例化
  • 调用B中的方法等…
网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发