位置: IT常识 - 正文

新一代状态管理工具 -- Pinia 上手指南

编辑:rootadmin
新一代状态管理工具 -- Pinia 上手指南 一:Pinia简介和五大优势

推荐整理分享新一代状态管理工具 -- Pinia 上手指南,希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:,内容如对您有帮助,希望把文章链接给更多的朋友!

Pinia是vue生态里Vuex的替代者,一个全新的vue状态管理库。在Vue3成为正式版以后,尤雨溪强势推荐的项目就是Pinia。 那先来看看Pinia比Vuex好的地方,也就是Pinia的五大优势。

可以对Vue2和Vue3做到很好的支持,也就是老项目也可以使用Pinia。抛弃了Mutations的操作,只有state、getters和actions.极大的简化了状态管理库的使用,让代码编写更加容易直观。不需要嵌套模块,符合Vue3的Composition api ,让代码更加扁平化。完整的TypeScript支持。Vue3版本的一大优势就是对TypeScript的支持,所以Pinia也做到了完整的支持。如果你对Vuex很熟悉的化,一定知道Vuex对TS的语法支持不是完整的(经常被吐槽)。代码更加简洁,可以实现很好的代码自动分割。Vue2的时代,写代码需要来回翻滚屏幕屏幕找变量,非常的麻烦,Vue3的Composition api完美了解决这个问题。 可以实现代码自动分割,pinia也同样继承了这个优点。

如果你说这五点有点太多了,记不住。可以简单总结Pinia的优势就是,更加简洁的语法,完美支持Vue3的Composition api 和 对TypesCcript的完美支持。这些优势和尤雨溪的强烈推荐。个人觉得很快Pinia就会完全取代Vuex,成为最适合Vue3的状态管理库。

二:Pinia开发环境安装

这里我就用Vite来创建一个Vue3项目为例。

1.使用Vite就需要先初始化vite:

npm init vite@latest

2.启动项目:

npm installnpm run dev

3.pinia的安装:

npm install pinia

可以看到安装的pinia最新版本是2.0.12

三:用Pinia的方式创建一个store1.在main.ts文件里引入Piniaimport { createPinia } from 'pinia'

引入后,通过createPinia( )方法,得到pinia的实例,然后将Pinia挂载到Vue根实例上。

2.创建store状态管理库

直接在/src目录下,新建一个store文件夹。有了文件夹之后,再创建一个index.ts文件。

这个文件里的代码,我们一般只做三件事:

定义状态容器(仓库)修改容器(仓库)中的 state仓库中的 action 的使用

第一步:定义状态容器(仓库)

import { defineStore} from 'pinia'export const mainStore = defineStore('main',{ state:()=>{ return {} }, getters:{}, actions:{}})

写完这段代码,你会感觉这个很像一个Vue的小组件,这也算是Pinia的一个优点。

defineStore( ) 方法的第一个参数:相当于为容器起一个名字。注意:这里的名字必须唯一,不能重复。defineStore( ) 方法的第二个参数:可以简单理解为一个配置对象,里边是对容器仓库的配置说明。当然这种说明是以对象的形式。state 属性: 用来存储全局的状态的,这里边定义的,就可以是为SPA里全局的状态了。getters属性: 用来监视或者说是计算状态的变化的,有缓存的功能。actions属性: 对state里数据变化的业务逻辑,需求不同,编写逻辑不同。说白了就是修改state全局状态数据的。

第二步:我们在Store里定义一个State,我们这里就写Hello Pinia!。

state:()=>{ return { helloPinia:'Hello Pinia!' }},

这时候这个helloPinia就是全局的状态数据,是每个页面和组件都可以通过Pinia方法读取到的。

3.在vue3组件里读取Store数据

在\src\components里,新建一个Hyy.vue的组件。代码如下:

先引入mainStore,然后通过mainStore得到store实例,就可以在组件里调用store里的state定义的状态数据了

<template> <div> <h2 class="">{{ store.helloPinia}}</h2> </div></template><script lang="ts">import { mainStore } from "../store/index";export default{ setup(){ const store = mainStore(); return{ store, } }}</script>

写好这个组件后,到App.vue里引入,就可以使用了:

<script setup lang="ts"> import Hyy from "./components/Hyy.vue";</script><template> <Hyy /></template><style></style>四:Pinia改变状态数据和注意事项1.新建组件,实现状态数据的改变

为了演示数据仓库的概念,新建一个组件。然后在一个组件里修改状态数据,看看另一个组件中的数据是否会改变。

在\components\文件夹下新建一个文件CountButton.vue。

<template> <h2 class="">{{ store.helloPinia }}</h2></template><script lang="ts">import { mainStore } from "../store/index";export default{ setup(){ const store = mainStore(); return{ store, } }}</script>

因为这里要做的是一个可以计数的组件,所以先到\store\index.ts的state属性中,增加一个状态数据count : 0。

\src\store\index.ts文件

state:()=>{ return { helloWorld:'HelloWorld', count:0 }},

有了这个状态数据后,再回到\components\CountButton.vue文件里,增加button和对应的业务逻辑(注意这里的业务逻辑就是修改状态数据)。代码如下:

<template> <div> <button @click="handleClick">点击增加</button> </div></template><script lang="ts">import { mainStore } from "../store/index";export default{ setup(){ const store = mainStore(); const handleClick = () => { store.count ++ } return{ store, handleClick } }}</script>

写好后,我们把count显示再Hyy.vue组件里。

\src\components\Hyy.vue

<template> <div> <h2>{{ store.helloPinia }}</h2> <h2>{{ store.count }}</h2> </div></template><script lang="ts">import { mainStore } from "../store/index";export default{ setup(){ const store = mainStore(); return{ store, } }}</script>

然后把CountButton加入到App.vue页面中。

<script setup lang="ts"> import Hyy from "./components/Hyy.vue"; import CountButton from "./components/CountButton.vue";</script><template> <Hyy /> <CountButton /></template><style></style>

做完这步后,就可以到浏览器中查看一下最终的实现效果。如果一切正常,你可以看到我们点击按钮后,两个组件的数据通过Pinia的状态管理,已经可以实现联动了。

注意:别踩了结构的坑

我在学习的时候发现了这样一个坑,在这里也和大家分享一下。希望小伙伴们不要踩坑。看下面的代码,我们是否可以简化一点

<template> <div> <h2>{{ store.helloPinia }}</h2> <h2>{{ store.count }}</h2> </div></template><script lang="ts">import { mainStore } from "../store/index";export default{ setup(){ const store = mainStore(); return{ store, } }}</script>

我们可以把store进行解构,然后直接template中直接这样读出数据。

<template> <div> <h2>{{ store.helloPinia }}</h2> <h2>{{ store.count }}</h2> <hr/> <h2>{{ helloPinia }}</h2> <h2>{{ count }}</h2> </div></template><script lang="ts">import { mainStore } from "../store/index";export default{ setup(){ const store = mainStore(); const {helloPinia,count} = store; return{ store, } }}</script>

这样看似简单,但通过解构的数据,只有一次作用,不是响应式数据(这就是我踩的坑了)。也就是说当你改变数据状态时,解构的状态数据不会发生变化。我们这时候再点击增加按钮,可以看到只有没结构的数据发生了变化。

于是我开始查找官方文档,显然Pinia团队也发现了这个问题,提供了storeToRefs( )方法。这个方法Pinia中,所以我们先用import引入。

import { storeToRefs } from "pinia";

有了storeToRefs( )方法后,就可以在解构的代码中,对store使用方法了。其实这时候就是把解构出来的数据作了ref响应式代理。所以数据拥有了响应式能力。

const { helloWorld, count } = storeToRefs(store);

这时候再到浏览器中测试一下,就一切正常了。补充:其实在Vuex中,直接解构数据也是不可以的。

五:Pinia修改状态数据的多种方式新一代状态管理工具 -- Pinia 上手指南

上面已经初步讲解了状态数据的修改,非常简单。但这只是数据修改的一种方式,还有三种方式。

第二种:使用$patch修改多条数据

接着上面编写的CountButton.vue 组件,我们再编写一个方法handleClickPatch( )这个方法。我们采用Pinia中的$patch的方式编写。

\scr\components\CountButtton.vue

const handleClickPatch = () => { store.$patch({ count:store.count + 2 })}

然后在里添加一个按钮,点击后执行这个方法。

<button @click="handleClickPatch">点击增加 - patch</button>

当然我在修改单条数据的时候,我喜欢这种直接修改的方式store.count++,因为足够简单。但是如果你同时修改多条数据,这里建议你使用$patch的方法。

比如现在我们点击按钮时,同时修改状态数据helloPinia,就可以写成这种方式:

const handleClickPatch = () => { store.$patch({ count:store.count + 2, helloPinia:store.helloPinia === 'Hello Pinia!' ? 'Hello World!' : 'Hello Pinia!' })}

那你说我在handleClick里直接写两行代码,是不是也可以实现这样的效果。通过代码测试,是可以实现的。哪为什么还要用$patch来做?

const handleClick = () => { store.count ++ store.helloPinia = store.helloPinia === 'Hello Pinia!' ? 'Hello World!' : 'Hello Pinia!'}

因为Pinia的官方网站,已经明确表示$ patch的方式是经过优化的,会加快修改速度,对程序的性能有很大的好处。所以如果你是多条数据同时更新状态数据,推荐使用$patch方式更新。

完整代码:

<template> <div> <button @click="handleClick">点击增加</button> <button @click="handleClickPatch">点击增加 - patch</button> </div></template><script lang="ts">import { mainStore } from "../store/index";export default{ setup(){ const store = mainStore(); const handleClick = () => { store.count ++ store.helloPinia = store.helloPinia === 'Hello Pinia!' ? 'Hello World!' : 'Hello Pinia!' } const handleClickPatch = () => { store.$patch({ count:store.count + 2, helloPinia:store.helloPinia === 'Hello Pinia!' ? 'Hello World!' : 'Hello Pinia!' }) } return{ store, handleClick, handleClickPatch } }}</script>第三种:$patch加函数的形式修改状态数据

上面的$patch方法,我们的参数使用的是一个对象。还有一种方式是传递函数,这种方法适合复杂数据的修改,比如数组、对象的修改。

再编写一个方法handleClickMethod( ),然后传递一个箭头函数进去。

const handleClickMethod = ()=> { store.$patch((state)=>{ state.count ++ state.helloPinia = state.helloPinia === 'Hello Pinia!' ? 'Hello World!' : 'Hello Pinia!' })}

这时候的state就是store仓库里的state,所以我们可以直接在函数里改变任何状态数据的值。为了看到效果,我们再编写一个按钮,来执行这个方法。

<button @click="handleClickPatch">点击增加 - $patch+函数</button>第四种:在actions中写好逻辑,再调用actions

如果你有一个修改的过程非常复杂,你可以先在store里,定义好actions中的函数,然后在组件里再调用函数。

我们先到\src\store\index.ts文件里,在actions的地方编写一个changeState( )方法,用来改变数据状态。代码如下:

actions: { changeState(){ this.count++ this.helloPinia = 'change helloPinia!!!' }}

有了这个changeState( )函数后,就可以在组件中调用这个函数来修改状态数据了。来到\src\components\CountButton.vue文件。编写一个新的方法handleClickActions( )方法。然后就可以用store调用changeState( )方法了。

const handleClickActions = ()=>{ store.changeState()}

然后再加入一个按钮,调用这个方法就可以了。

<button @click="handleClickActions">点击增加 - actions</button>

注意:在用actions的时候,不能使用箭头函数,因为箭头函数绑定是外部的this。这个小伙伴们需要注意一下就可以了。

六:Pinia中的Getters使用1. 新增状态属性和编写Getters

先在\src\store\index.ts文件的state里增加一个phone的状态数据。

state:() => { return { helloPinia: 'Hello Pinia!', count: 0, phone:'17808098401' } },

然后再getters里编写一个方法,这个方法就是隐藏手机号中间四位的,隐藏的方法就是使用正则表达式替换。代码如下:

getters:{ phoneHidden(state){ return state.phone.toString().replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2') }},

然后到\src\components\Hyy.vue中直接显示隐藏号码显示: 这时候打开浏览器,可以看到电话号码已经被隐藏了。

2. Getters的缓存特性

Getters是有缓存特性的,现在我们的Hyy组件中调用了两次phoneHidden吧,这时我们在index.ts状态仓库里增加一个console.log('PhoneHidden被调用了’)。

getters: { phoneHidden(): string{ console.log('PhoneHidden被调用了') return this.phone.toString().replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2') } },

然后回到浏览器中按F12打开查看Console面板,可以看到只显示了一次PhoneHidden被调用了,也变相说明了getters是有缓存的,虽然调用多次,但是值一样就不会被多次调用。

在\src\components\CountButton.vue文件下,新编写一个方法handleClickChangePhone。用来改变电话号码。

// 点击按钮的对应函数const handleClickChangePhone = () => { store.phone = "17800000000";}

有了函数后,再编写一个按钮,触发这个函数,电话号码就变化了。

<button @click="handleClickChangePhone">Getter缓存</button>

当电话号码改变时,Getters会自动工作,对应的phoneHidden方法也会随着调用一次,清除以前的数据缓存。

3. 关于this的使用

写完上面的小案例,相信你对Pinia的Getters的使用已经掌握了。这时候再回到\src\store\index.ts文件里。我们看到actions里是直接可以使用this关键字操作的。

那我们思考一个问题,在getters里可以用this进行操作吗?

答案时可以的,修改代码为下面的形式:

getters: { phoneHidden():string{ return this.phone.toString().replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2') }},

因为我们使用的是TS,所以如果我们不传state, TypeScript是无法自动推到出来返回的数据类型的,所以这里我们要标明返回类型为String。就不会提示错误了。

总结:这节我们学习了Pinia中Getters的用法,它和Vue中的计算属性非常类似,但是拥有缓存属性。我们在编写Getters的时候,不仅可以传递state参数用来改变状态数据,还可以直接使用关键字this来改变数据。

七:Pinia中Store的互相调用

在上面代码中我们一直只使用了一个Store仓库,在真实项目中我们往往是有多个Store的。有多个Stroe时,就会涉及Store内部的互相调用问题。

第一步:新建一个Store仓库

在\src\store下新建一个Hyy.ts文件:

import { defineStore } from 'pinia'export const hyyStore = defineStore("hyyStore", { state:() => { return { list:["黄黄","小黄","黄小黄"] } }, getters: { }, actions: { }})

这是一个非常简单的仓库,只有state(状态数据),需要注意的是ID要是唯一的。有了这个仓库后,就可以回到index.ts这个仓库中调用了。

第二步:先引入Hyy这个store。import { hyyStore } from './hyy'第三步:然后在actions部分加一个getList( )方法。

这部分就写的很简单了,只是用console.log( )打印到控制台 上就可以了。

actions: { changeState(){ this.count++ this.helloPinia = 'change helloPinia!!!' }, getList(){ console.log(hyyStore().list) }}

为了方便学习,这里给出\src\store\index.ts的全部代码:

import { defineStore } from 'pinia'import { hyyStore } from './hyy'export const mainStore = defineStore("mian", { state:() => { return { helloPinia: 'Hello Pinia!', count: 0, phone:'17808098401' } }, getters: { phoneHidden():string{ return this.phone.toString().replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2') } }, actions: { changeState(){ this.count++ this.helloPinia = 'change helloPinia!!!' }, getList(){ console.log(hyyStore().list) } }})

这样就实现了两个store中互相调用。

第四步:为了看到效果,我们依然来到\src\components\CountButton.vue这个文件里,写一个新的方法,就叫做getList( )。const getList = () => { store.getList();};

有了getList( )方法后,在template部分,写一个按钮进行触发。

<button @click="getList">Pinia中store的相互调用</button>

到浏览器中查看效果,按F12打开控制台,点击按钮后,可以看到跨Store的状态数据调用已经成功了。

本文链接地址:https://www.jiuchutong.com/zhishi/295285.html 转载请保留说明!

上一篇:html--盒子的边框属性(border)(html盒子边框圆角)

下一篇:Vue3 之 过滤器(vue中过滤器有什么作用及详解)

  • b站怎么设置循环播放(b站怎么设置循环播放一个视频)

    b站怎么设置循环播放(b站怎么设置循环播放一个视频)

  • 华为手机显示与文字大小在哪里(华为手机显示与亮度在哪里)

    华为手机显示与文字大小在哪里(华为手机显示与亮度在哪里)

  • qq画画红包怎么识别(qq画画红包多来a梦)

    qq画画红包怎么识别(qq画画红包多来a梦)

  • 宽带突然不能用了是什么原因(宽带突然不能用了怎么回事移动)

    宽带突然不能用了是什么原因(宽带突然不能用了怎么回事移动)

  • 默认卡是什么意思(默认卡是什么意思呀)

    默认卡是什么意思(默认卡是什么意思呀)

  • 已经下载的文件哪里找(如何查找微信已经下载的文件)

    已经下载的文件哪里找(如何查找微信已经下载的文件)

  • 华为荣耀9a是不是华为(华为荣耀九a)

    华为荣耀9a是不是华为(华为荣耀九a)

  • 手机号码过期什么意思(手机号码过期是怎么回事,还能用吗)

    手机号码过期什么意思(手机号码过期是怎么回事,还能用吗)

  • plk-tl01h是什么型号手机(plk-al01)

    plk-tl01h是什么型号手机(plk-al01)

  • 苹果手机怎么放歌没声音(苹果手机怎么放音乐)

    苹果手机怎么放歌没声音(苹果手机怎么放音乐)

  • 华为笔记本pin码是什么(华为笔记本pin码忘记了怎么解锁)

    华为笔记本pin码是什么(华为笔记本pin码忘记了怎么解锁)

  • 乐视手机为什么卡(乐视手机为什么连上无线网却不能上)

    乐视手机为什么卡(乐视手机为什么连上无线网却不能上)

  • 手机怎么点外卖(手机怎么叫外卖送餐)

    手机怎么点外卖(手机怎么叫外卖送餐)

  • 苹果11如何设置24小时显示(苹果11如何设置26键拼音)

    苹果11如何设置24小时显示(苹果11如何设置26键拼音)

  • 苹果7nfc功能怎么开启(苹果7nfc功能怎么复制门禁卡)

    苹果7nfc功能怎么开启(苹果7nfc功能怎么复制门禁卡)

  • 苹果xr副号上网支持4g吗(苹果副号不能上网)

    苹果xr副号上网支持4g吗(苹果副号不能上网)

  • 红光笔最远能打多少距离(红光笔glint)

    红光笔最远能打多少距离(红光笔glint)

  • opporenoz处理器相当于骁龙多少(opporenoz的处理器)

    opporenoz处理器相当于骁龙多少(opporenoz的处理器)

  • 安卓微信共享位置修改(安卓微信共享位置修改软件)

    安卓微信共享位置修改(安卓微信共享位置修改软件)

  • 苹果xsmax有哪些新功能(苹果xsmax有哪些APP好用)

    苹果xsmax有哪些新功能(苹果xsmax有哪些APP好用)

  • app图标尺寸(APP图标尺寸大小)

    app图标尺寸(APP图标尺寸大小)

  • 中华英才网如何找工作(中华英才网如何注册)

    中华英才网如何找工作(中华英才网如何注册)

  • 键盘驱动怎么修复(键盘驱动坏了怎么重装系统)

    键盘驱动怎么修复(键盘驱动坏了怎么重装系统)

  • win10蜘蛛纸牌游戏在哪? win10玩蜘蛛纸牌的技巧(w10的蜘蛛纸牌)

    win10蜘蛛纸牌游戏在哪? win10玩蜘蛛纸牌的技巧(w10的蜘蛛纸牌)

  • KB5004296无法安装,提示错误代码:0x800f0990的解决方法

    KB5004296无法安装,提示错误代码:0x800f0990的解决方法

  • ImageDrive.exe进程什么文件 ImageDrive是什么进程(image driver)

    ImageDrive.exe进程什么文件 ImageDrive是什么进程(image driver)

  • Vant UI 中 van-collapse 下拉折叠面板如何默认展开第一项

    Vant UI 中 van-collapse 下拉折叠面板如何默认展开第一项

  • 使用Python实现一个堆栈结构(利用python)

    使用Python实现一个堆栈结构(利用python)

  • 个人出售普通住宅应当缴纳哪些税
  • 使用增值税发票的条件
  • 企业筹建期间契税账务处理
  • 信息技术服务可以简易征收吗
  • 增值税电子普通发票和增值税专用发票区别
  • 资产处置收益对应科目
  • 预告登记与备案的区别
  • 应缴国库款和应交税款
  • 增值税广告服务包括哪些内容
  • 当月发票开错了已经红冲怎么做分录?
  • 收到其他银行划回的款项属于什么科目
  • 收入做多增值税怎么算
  • 应税销售额是指
  • 公司股权转移怎么办理
  • 有税收完税证明还需要发票吗
  • 小微企业的资产总额看哪里判断的
  • 销售后换回产品的账务处理怎么做?
  • 汽车加油票可以开专票吗
  • 未办土地有偿使用手续多少钱
  • 境外代扣代缴所得税
  • word文档打印时不打印批注
  • 怎么解决笔记本电脑卡顿问题
  • 蝾螈白话怎么读
  • 无线路由器温度范围
  • php assign
  • php常用的魔术方法有哪些
  • 坏账损失和坏账准备
  • threejs loader
  • element-ui表格
  • 记账凭证的总账科目是什么
  • yolov1网络结构图详解
  • 接受捐赠和对外捐赠分录
  • 支付水电费增值税账务处理
  • 搭建自己的php框架
  • php验证码功能怎么实现
  • 现金流量表期初现金余额本年累计
  • angular 初学者快速上手教程
  • spring integration使用:消息转换器
  • 旅游业发票的税率是多少
  • 公益性捐赠递延注会
  • 工程类什么情况下可以三方询价
  • 机器学习——果蔬分类
  • 理财产品的分类
  • sql server 2016 sp3
  • 小规模企业现金流量表
  • 对公账户转到个体工商户
  • 企业所得税年报更正申报怎么操作
  • 生产成本核算的步骤
  • 增值税发票上注明的价款包含增值税吗
  • 两种原因
  • 单位补扣社保算漏交吗
  • 印花税每个月都计提吗
  • 给客户的回扣怎么表达
  • 应收账款和应付账款的管理
  • 企业设备维修
  • 政府补助计入资本公积吗
  • 企业间借款利息涉税处理
  • 库存股算什么科目
  • 公司坏账率一般多少
  • 检查mysql是否正常
  • xpkw
  • spkrmon.exe - spkrmon是什么进程
  • windows7英雄联盟老是崩溃
  • qq空间好友评论别人看不到
  • linux的top参数
  • 如何使用朋友的山姆卡
  • js绑定onchange
  • 如何创建node项目
  • 在线linux模拟环境
  • javascript中的函数如何理解
  • shell脚本实现文件重命名
  • 能用javascript 最终
  • javascript运用
  • python如何编写
  • javascript基础笔记
  • 个人所得税税前扣除是什么意思
  • 留抵税额怎么形成的
  • 联合国英文全称和缩写
  • 重庆市九龙坡税务局行政服务中心电话
  • 电子税务局怎么找回用户名
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设