Vue全新一代状态管理库 Pinia一篇通
Posted 旧梦星轨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue全新一代状态管理库 Pinia一篇通相关的知识,希望对你有一定的参考价值。
文章目录
前言
Vue3 已经推出相当长一段时间了,同时其周边的生态支持,也越来越完善化了,如今Vue3 已经成为了官方的默认版本了,所以伴随着,目前处于一个生态集体过度的一个阶段,一些新的Api 支持也需要我们去了解学习,本章节文章,
带来的是 Vue 的全新一代 状态管理库 Pinia
,Pinia 已完美适配Vue3,并且 也获得Vue作者 尤雨溪,及Vue 官方推荐在Vue3中使用 Pinia 来实现状态管理,那么Pinia,究竟有什么厉害的地方?,本章节将为大家讲述 Pinia 的新特征!
1. Pinia 是什么?
如果你学习过 Vue2,那么你也就一定使用过 Vuex,想必大家也都知道,Vuex 在Vue2 中 充当的是集中式状态管理的角色,所谓集中式状态管理,就是把多个组件需要共享的的数据,整理到一个集中的地方进行托管,然后任何一个组件都能够从这里面读取到数据,它也是Vue 生态中的重要组成部分!,在 Vue3 中,你依然可以使用传统的 Vuex 来实现状态管理,但官方推荐在 Vue3 使用 Pinia 来做状态管理,你可以理解成 Pinia 就是 Vuex 的升级版!
Pinia 起始于 2019 年 11 月左右的一次实验,其目的是设计一个拥有组合式 API 的 Vue 状态管理库。
1.1 为什么取名叫 Pinia?
Pinia (发音为 /piːnjʌ/,类似英文中的 “peenya”) 是最接近有效包名 piña (西班牙语中的 pineapple,即“菠萝”) 的词。 菠萝花实际上是一组各自独立的花朵,它们结合在一起,由此形成一个多重的水果。 与 Store 类似,每一个都是独立诞生的,但最终它们都是相互联系的,
用来比喻 把一个一个的小格子数据,集中式管理在一起
,所以也有很多开发者,习惯性 的把 Pinia 称呼 为 “小菠萝”!
1.2. 为什么要使用 Pinia ?
很多小伙伴,看到这里也会表示疑惑,既然 Pinia 和 Vuex 的作用是 一样的,那么为什么 还需要 学习 Pinia ?它到底有什么 特别的优点吗?… 针对大家产生的疑惑,这也是正常的思考逻辑,毕竟 学习一件东西,也是需要一定成本的,如果,两者区别意义不大,那么确实是该思考,要不要学。那么我在这里告诉大家 Pinia ,非常值得去学习,他拥有很多 Vuex 不具备的优点,以及去除了很多冗余的部分!
优点
:
- Pinia 同时支持 Vue2 以及 Vue3 ,这让同时使用 两个版本的小伙伴更容易上手。
- Pinia 中 只存在了 State,getter,action,
剔除掉了 Vuex 中的 Mutation 以及 Module
。 - Pinia 中的 action 可以
同时支持同步任务和异步任务
。 - 更友好的支持了 TypeScript ,无需创建自定义复杂包装器来支持 TypeScript,所有内容都是类型化的,并且 API 的设计方式尽可能利用
TS 类型推断
。 - Pinia在
修改状态的时候不需要通过其他api
,如:vuex需要通过commit,dispatch去修改,所以在语法上比vuex更容易理解和使用灵活。 - 由于去除掉了 Module ,无需再创建各个模块嵌套了,Vuex 中,如果数据过多,通常会通过划分模块来进行管理,而 Pinia 中,
每个 Store 都是独立的
,互不影响。 - 支持
服务端渲染
。 - …
注意事项:
想要学习 Pinia 最好要有 Vue3 的基础 ,明白组合式 Api 的概念,本篇文章的讲解是基于 Vue3 来使用的,虽然 Pinia 也能向下兼容 Vue2 ,但是却并不常用,在 Vue2 中 使用 Pinia 毕竟是少数!
点击学习 => Vue3 新特征 上手指南!
2. 安装 Pinia
在项目根目录下 使用命令安装
yarn add pinia
# 或者使用 npm
npm install pinia
安装完成后 在 main.js 中,将 创建一个 pinia 实例 (根 store) 挂载到 应用实例身上。
import createApp from 'vue'
import createPinia from 'pinia'
import App from './App.vue'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
app.mount('#app')
官网 对 Store 的描述:
2.1.创建 Store
在 Pinia 中,Store 是使用 一个 defineStore() 函数 定义的,它的第一个参数要求是一个独一无二
的名字,这个名字 ,也被用作 id ,是必须传入的, Pinia 将用它来连接 store 和 devtools。为了养成习惯性的用法,将返回的函数命名为 use… 是一个符合组合式函数风格的约定。
import defineStore from 'pinia'
// 你可以对 `defineStore()` 的返回值进行任意命名,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。(比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useAlertsStore = defineStore('alerts',
// 其他配置...
)
defineStore() 的第二个参数可接受两种类型的值:Setup 函数或 Option 对象
2.1.1. Option 类型 Store
export const useAlertsStore = defineStore('counter',
state: () => ( count: 17 ),
getters:
double: (state) => state.count * 5,
,
actions:
increment()
this.count++ //这里的 this ,指向 state 所返回的 数据对象
,
,
)
你可以认为 state 是 store 的数据 (data),getters 是 store 的计算属性 (computed),而 actions 则是方法 (methods)。
2.1.2 Setup 函数类型 Store
import ref , computed from 'vue'
export const useCounterStore = defineStore('main', () =>
let num = ref(4);
let processnum = computed(() =>
return num.value * 26
)
let Events = () =>
num.value++
return num, processnum, Events
)
在 Setup Store 中:
- ref() 就是 state 属性
- computed() 就是 getters
- function() 就是 actions
注意
:所有 Store 在实例化之前,Store 仓库是不会被创建的!
2.1.3 模板中使用
<template>
<!-- Option Store 数据 方法 -->
<h1> AlertsStore.count</h1>
<h1> AlertsStore.double </h1>
<el-button type="primary" @click="addclcik">点击递增</el-button>
<!-- setup Store 数据方法 -->
<h1> counterStore.num </h1>
<h1> counterStore.processnum </h1>
<el-button type="primary" @click="counterStore.Events">点击递增</el-button>
</template>
<script>
import useAlertsStore, useCounterStore from '../../../Pinia/store'; // 导入 Store
export default
name: 'home',
setup(props)
const AlertsStore = useAlertsStore(); //拿到 Option Store 实例
const counterStore = useCounterStore(); // 拿到 setup Store 实例
let addclcik= (() =>
AlertsStore.increment()
)
return
AlertsStore,
addclcik,
counterStore
</script>
模板中对数据方法定义解构:
当有时候 Store 中的数据过多,嵌套多层,这时候在模板中,书写的 数据层级 会显得特别冗余,对此,我们首先想到的是对数据进行解构,由于 store 是一个用 reactive 包裹的对象,所以,我们如果直接对其解构,则会丢失响应式。
所以为了应对 丢失响应式 的问题, Pinia 官方 提供了一个 Api 函数 storeToRefs ()
注意:
: storeToRefs ()
只能 解构 状态数据 ,不能够解构 事件方法 !
<template>
<!-- Option Store 数据 方法 -->
<h1> count </h1>
<h1> double </h1>
<el-button type="primary" @click="addclcik">点击递增</el-button>
<!-- setup Store 数据方法 -->
<h1> num </h1>
<h1> processnum </h1>
<el-button type="primary" @click="Events">点击递增</el-button>
</template>
<script>
import useAlertsStore, useCounterStore from '../../../Pinia/store'; // 导入 Store
import storeToRefs from 'pinia'
export default
name: 'home',
setup(props)
const AlertsStore = useAlertsStore(); //拿到 Option Store 实例
const CounterStore = useCounterStore(); // 拿到 setup Store 实例
// const count, double = AlertsStore; // 会丢失响应式
// const num, processnum = CounterStore; // 会丢失响应式
const count, double = storeToRefs(AlertsStore); // 不会丢失响应式
const num, processnum = storeToRefs(CounterStore); // 不 会丢失响应式
const increment = AlertsStore;
const Events = CounterStore;
let addclcik = (() =>
increment()
)
return
count,
double,
increment,
addclcik,
num,
processnum,
Events
</script>
3. State 的使用事项(Option Store )
官方推荐在任何时候,state,都应该是一个函数的返回值,为了防止数据污染,这使得 Pinia 可以同时支持服务端和客户端。并且强力推荐 使用箭头函数,因为箭头函数 ,可以更好的适配TS 做类型 推理!
export const useStore = defineStore('counter',
state: () => (
count: 17,
name: "张三"
),
)
3.1 读取 State
默认情况下,你可以通过 store 实例访问 state,直接对其进行读写。
const store = useStore()
store.count++
const count, name = storeToRefs(store ); // 同时也能像上面提到的,采用解构 的方式读取
3.2 重置 State
可以通过调用 store 的 $reset() 方法将 state 重置为初始值。
const store = useStore()
store.$reset()
3.3 修改变更 State (批量修改)
除了用 store.count++ 直接改变 store,你还可以调用 $patch 方法。它允许你用一个 state 的补丁对象在同一时间更改多个属性:
store.$patch(
count: store.count + 10,
name: '张三丰',
)
// $patch 不会影响 ,源数据 中不需要修改的值, 底层做了 key 字段映射匹配,只会去修改,我传入的 key值
不过,用这种语法的话,有些变更真的很难实现或者很耗时:任何集合的修改(例如,向数组中添加、移除一个元素或是做 splice 操作)都需要你创建一个新的集合。因此,$patch 方法也接受一个函数来组合这种难以用补丁对象实现的变更。
store.$patch((state) =>
state.count = 25
state.name = "张三"
)
如果,业务逻辑相对比较复杂,也可以将 ,修改数据的方法,封装 在 Action 中
,使页面中减少冗余的代码。
4.getter 使用细节
定义 getter 方法函数
export const state = defineStore('counter',
state: () => (
count: 17,
name: "张三"
),
getters:
double(state) //接收 一个参数 可以拿到 store 实例身上的 数据
return state.count * 5
return this.count * 5 //如果 这里没有传递参数,也可以通过 this,也能 访问到 store 实例 数据,这里的 this 指向 store 实例
//注意, 使用 this 访问 store 这样的 写法,会影响 TS做 类型 推理。只能 手动 指定类型
,
double: (state) => state.count * 5, //所以,官方建议推荐使用 箭头函数,可以更好的 配合 Ts 做类型推理
cases(state) // 1275
// 由于这里 可以 通过 this 访问 store 实例,所以在 当前 getter 里面 也可以访问 拿到其他 getter 的值。
return this.double * 15
,
)
4.1 getter 接收外部传进来的 参数
export const useAlertsStore = defineStore('counter',
state: () => (
count: 17,
name: "张三"
),
getters:
double: (state) => (val) => //返回 函数 接收 一个 外部传入参数
return state.count * val
,
,
)
在模板中 调用 double 函数时 ,直接传入参数就行
注意
:请注意,当你这样做时,getter 将不再被缓存,它们只是一个被你调用的函数。
4.2 访问 其他 Store 仓库中的数据
export const useAlertsStore = defineStore('counter',
state: () => (
count: 17,
name: "张三"
),
getters:
double: (state) => (val) =>
let CounterStore = useCounterStore(); //直接 可以 获取到 其他仓库的 实例。
return state.count * CounterStore.processnum + val //1773
,
,
)
export const useCounterStore = defineStore('main', () =>
let num = ref(4);
let processnum = computed(() =>
return num.value * 26
)
let Events = () =>
num.value++
return num, processnum, Events
)
5. action
action 中,既可以开启 同步任务,也可以 开启异步 任务,同时也能 访问 其他 Store 仓库 中的 方法数据。,方法和,上面 gtter 访问 其他 仓库 同理。,
export const useAlertsStore = defineStore('counter',
state: () => (
count: 17,
name: "张三"
),
getters:
double: (state) => (val) =>
let CounterStore = useCounterStore();
return state.count * CounterStore.processnum + val
,
,
actions:
increment() //actions 里面的 函数 只能通过 this 来访问数据 ,不能使用 箭头函数 ,只能定义普通函数。
this.count++ //这里的 this ,指向 state 所返回的 数据对象
//可以在这里开启异步任务
,
,
)
总结
以上就是本章节 所讲的 有关 Pinia 的内容,Pinia 作为 Vue3 生态圈中的新一代 状态管理库,后面肯定会成为 Vue 官方的主推生态。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 install
npm run dev
3.pinia的安装:
npm install pinia
可以看到安装的pinia最新版本是2.0.12
三:用Pinia的方式创建一个store
1.在main.ts文件里引入Pinia
import 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修改状态数据的多种方式
上面已经初步讲解了状态数据的修改,非常简单。但这只是数据修改的一种方式,还有三种方式。
第二种:使用$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(/^(\\d3)\\d4(\\d4)$/, '$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(/^(\\d3)\\d4(\\d4)$/, '$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(/^(\\d3)\\d4(\\d4)$/, '$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(/^(\\d3)\\d4(\\d4)$/, '$1****$2')
,
actions:
changeState()
this.count++
this.helloPinia = 'change helloPinia!!!'
,
getList()
console.log(hyyStore().listpinia--新一代vue状态管理方案(上手篇)