vue3 基础-Pinia 可能替代 Vuex 的全局数据状态管理
Pinia 初体验
Pinia.js是由Vue.js团队核心成员开发的新一代状态管理器,使用Composition Api进行重新设计的,也被视为下一代Vuex。
Pinia是一个Vue的状态管理库,允许跨组件、跨页面进行全局共享状态,也由于其设计的简洁性、和对typescript的良好支持,取代Vuex指日可待。
或许,你在想在vue3中Composition API完全可以使用响应式变量进行全局共享状态,为什么还需要Pinia呢?其实你忽略的一点,你这样做在单页面进行应用是完全可以的,但是如果页面时服务端进行渲染呈现可能就有问题了.
安装
npm install pinia
引入到项目
在 main.js 中只需要调用createPinia()方法将pinia实例化,然后挂载到vue实例上就可以了.
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.mount('#app')
下一步就应该去创建我们的数据仓库store了,store中存储的是我们需要共享的数据.
创建store需要调用pinia中的defineStore方法,该方法接受两个参数,第一个参数是store的唯一 id,第二个参数是store的配置属性.
defineStore方法配置store属性时,有两种写法,一种是Option 对象形式,一种是Setup 函数形式。
对于 Option 的方式和 Vuex 是一样的, 区别在于, 取消了 Mutations 而让 Actions 同时能进行同步和异步的操作, 这很方便.
在 src 目录下创建一个 store / index.js 的文件:
import { defineStore } from 'pinia'
// 模块1
export const useStore = defineStore("store", {
state: () => ({
name: 'youge',
age: 18
}),
// 同步 / 异步 都可以写在一起, 这比 Veux 方便多了
actions: {
changeName(name) {
this.name = name
},
aysncChangeName(name) {
setTimeout(() => {
this.name = name
}, 2000)
}
}
})
// 模块2
// export const useStore2 = defineStore("store2", { })
我其实还是更偏向这种 vuex 风格写法的.
当然用 setup 的写法也支持的.
import { ref } from 'vue'
import { defineStore } from 'pinia'
// 模块1
export const useStore = defineStore('store2', () => {
// 原来的 state 数据直接进行定义即可, 主要要响应式
let name = ref('youge')
let age = ref(18)
// 同步/异步任务, 直接定义成普通函数即可
const changeName = (newName) => name.value = newName
function aysncChangeName(newName) {
setTimeout(() => {
name.value = newName
}, 2000);
}
// 划重点! 这里一定要 return 出去哦
return { name, changeName, aysncChangeName }
})
// 模块2
// export const useStore2 = defineStore("store2", () => { })
则对应的视图, 这里以 setup 的风格:
<template>
<div>
<p>同步获取 store 的 name 为: {{ name }}</p>
<p>异步获取 store 的 name 为: {{ name }}</p>
</div>
<button @click="changeName('jack')">同步修改数据</button>
<button @click="aysncChangeName('jack')">异步修改数据</button>
</template>
<script setup>
// import Father from './Father.vue'
import { useStore } from './store'
import { storeToRefs } from 'pinia'
const store = useStore()
// store 的方法, 直接解构使用就行
const { changeName, aysncChangeName } = store
// store 的变量就需要包装一下成响应式了
const { name } = storeToRefs(store)
</script>
如果用 setup 的写法呢, 需注意变量结构会丢失响应式, 需要用 pinia 提供的 storeToRefs 包装一下即可.
<template>
<!-- <div>
<Father />
</div> -->
<div>
<p>同步获取 store 的 name 为: {{ name }}</p>
<p>异步获取 store 的 name 为: {{ name }}</p>
</div>
<button @click="changeName('jack')">同步修改数据</button>
<button @click="aysncChangeName('jack')">异步修改数据</button>
<button @click="handleClick('jack')">直接修改数据</button>
</template>
<script setup>
// import Father from './Father.vue'
import { useStore } from './store'
import { storeToRefs } from 'pinia'
const store = useStore()
const { changeName, aysncChangeName } = store
// store 的变量就需要包装一下成响应式了
const { name } = storeToRefs(store)
const handleClick = (newName) => store.name = newName
</script>
或者直接用对象.属性的方式, 不通过结构也行的, 这样也不会丢失响应式.
<template>
<!-- <div>
<Father />
</div> -->
<div>
<p>同步获取 store 的 name 为: {{ store.name }}</p>
<p>异步获取 store 的 name 为: {{ store.name }}</p>
</div>
<!-- 1. 同步 / 异步 修改 -->
<button @click="store.changeName('jack')">同步修改数据</button>
<button @click="store.aysncChangeName('jack')">异步修改数据</button>
<!-- 2. 直接在标签上改 -->
<button @click="handleClick('jack')">直接修改数据</button>
</template>
<script setup>
import { useStore } from './store'
const store = useStore()
const handleClick = (newName) => store.name = newName
</script>
子组件调用触发的 getActivePinia( ) 问题
原因是 pinia 在 main.js 中还没有注册好, 便已在其他文件 (组件) 中使用了它, 就会报错了, 方案就是提前注册呀.
首先, 在 App.vue 同级目录下新建一个名为 "pinia.js" 的文件, 当然文件名和位置都是可以任意的, 这里只是建议.
// src/pinix.js
import { createPinia } from "pinia"
const pinia = createPinia()
export default pinia
然后, 在 main.js 进行引用注册 pinia.
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import pinia from './pinia'
const app = createApp(App)
app.use(pinia)
app.mount('#app')
最后, 在需要用到全局 store 的地方分别进行引入 即可.
如父组件 App.vue
<template>
<div>
<p>同步获取 store 的 name 为: {{ store.name }}</p>
<p>异步获取 store 的 name 为: {{ store.name }}</p>
</div>
<!-- 1. 同步 / 异步 修改 -->
<button @click="store.changeName('jack')">同步修改数据</button>
<button @click="store.aysncChangeName('jack')">异步修改数据</button>
<!-- 2. 直接在标签修改 -->
<button @click="handleClick('jack')">直接修改数据</button>
<p>
子组件:
<Child />
</p>
</template>
<script setup>
// import Father from './Father.vue'
import Child from './Child.vue'
import { useStore } from './store'
import pinia from './pinia'
const store = useStore(pinia)
const handleClick = (newName) => store.name = newName
</script>
里面的子组件 Child.vue, 注意在 script 标签中一定要加上 setup
<template>
<div>
数据: {{ store.name }}
</div>
</template>
<script setup>
import { useStore } from './store'
import pinia from './pinia'
const store = useStore(pinia)
</script>
页面:
同步获取 store 的 name 为: youge
异步获取 store 的 name 为: youge
(同步修改数据) (异步修改数据) (直接修改数据)
子组件:
数据: youge
这真的是, 用 Pinia 感觉就和没有用一样丝滑.
不过这里也只是初步体验, 具体使用还是待考察中.
vue3 基础-Pinia 可能替代 Vuex 的全局数据状态管理的更多相关文章
- 使用 react 的 hooks 进行全局的状态管理
使用 react 的 hooks 进行全局的状态管理 React 最新正式版已经支持了 Hooks API,先快速过一下新的 API 和大概的用法. // useState,简单粗暴,setState ...
- computed 和 watch 组合使用,监听数据全局数据状态
我要实现的就是,当接口返回数据时,我在任何组件中都能感知到到该数据的变化,然后根据业务逻辑进行处理.展示. 实现这个效果的方式很多,比如当接口返回数据后,就emit这数据,在另外组件中on接收渲染即可 ...
- 基于 vite 创建 vue3 全家桶项目(vite + vue3 + tsx + pinia)
vite 最近非常火,它是 vue 作者尤大神发布前端构建工具,底层基于 Rollup,无论是启动速度还是热加载速度都非常快.vite 随 vue3 正式版一起发布,刚开始的时候与 vue 绑定在一起 ...
- Vue3 Vite3 状态管理 pinia 基本使用、持久化、在路由守卫中的使用
在<基于 vite 创建 vue3 项目>一文中整合了 pinia,有不少伙伴不知道 pinia 是什么,本文简单介绍 pinia.主要包括三方面: pinia 的基本用法,在<基于 ...
- 23年用vuex进行状态管理out了,都开始用pinia啦!
1 Vue2项目中,Vuex状态管理工具,几乎可以说是必不可少的了.而在Vu3中,尤大大推荐我们使用pinia(拍你啊)进行状态管理,咱得听话,用就完了. 使用之前我们来看一下,使用 pinia 给我 ...
- 实战进阶 Vue3+Axios+pinia
实战进阶 Vue3+Axios+pinia 创建文件utils/request.js import Axios from 'axios'; export const request = Axios.c ...
- Redux/Mobx/Akita/Vuex对比 - 选择更适合低代码场景的状态管理方案
近期准备开发一个数据分析 SDK,定位是作为数据中台向外输出数据分析能力的载体,前端的功能表现类似低代码平台的各种拖拉拽.作为中台能力的载体,SDK 未来很大概率会需要支持多种视图层框架,比如Vue2 ...
- 微信小程序全局状态管理 wxscv
微信小程序中,数据状态不同页面中不能跨页面同步更新,也就是缺失类似vuex,mobx,redux全局的数据状态管理功能. 有些人移植了这些库,但是毕竟不是微信小程序生态的东西. Tencent也发布了 ...
- 状态管理之 Flux、Redux、Vuex、MobX(概念篇)
本文是对 Flux.Redux.Vuex.MobX 几种常用状态管理模式的总结,偏向于概念层面,不涉及过多代码. 状态管理 什么是状态管理? 状态管理就是,把组件之间需要共享的状态抽取出来,遵循特定的 ...
- 2022.07.13 vue3下pinia的简单使用及持久化
使用前说明: 当前demo使用了vue3 + vite + typescript + pinia搭建的简单项目,主要介绍了在单文件组件(sfc)基础上使用pinia的用法,懒得看api的兄弟们,来这瞅 ...
随机推荐
- [BZOJ4833] 最小公倍佩尔数 题解
在这篇题解中,我会将各个部分的证明分成不同的推导过程,以达到逐一击破的效果. 引理 1:\(f(n)=2f(n-1)+f(n-2)\) 我的证明挺繁琐的,过程如下: \[(1+\sqrt 2)^{n- ...
- [SDOI2016] 数字配对 题解
发现题目中描述的配对条件可以理解为:\(pc_i-pc_j=1\) 且 \(a_i\bmod a_j=0\),其中 \(pc_i\) 表示 \(a_i\) 的质因数个数. 自然想到以 \(pc\) 奇 ...
- Java中ArrayList的常见用法
Java 中的 ArrayList 是一个非常常用的动态数组,它属于 Java 集合框架的一部分.与普通数组不同,ArrayList 可以在需要时动态调整其大小.以下是 ArrayList 的一些详细 ...
- Arduino LED流水灯·基础实验
Arduino初学IO控制,流水灯实验是很好的学习对象.分两个进程学习. 一.假流水灯,即基础效果实现 二.真流水灯,即采用PWM模拟真实流水渐变效果 我们设立5盏灯,正极分别连接数字口(Digita ...
- Flink学习(十四) Flink 窗口、时间和水位线
Flink 框架中支持事件时间.摄入时间和处理时间三种.而当我们在流式计算环境中数据从 Source 产生,再到转换和输出,这个过程由于网络和反压的原因会导致消息乱序.因此,需要有一个机制来解决这个问 ...
- 使用DeepSeek-R1分析电影票房
最近在学习DeepSeek-R1本地化部署的相关知识,看到了1个比较有意思的视频. 在该视频中,其主要逻辑就是当用户上传1个Excel后,之后就可以通过交互式的方式对这个Excel中的数据进行分析.但 ...
- 当懒惰遇上AI:我如何用Coze让大模型帮我整理2.5万字课程笔记
能写代码绝不动手,能用AI绝不写代码 -- AI粉嫩特攻队信条 通过本文学会打造这个AI工具,只有一个要求:识字且会上网! 一个小困扰 有朋友最近在上一位大佬的线上直播课程,感叹道: "老师 ...
- 全面的C#/.NET/.NET Core面试宝典(永久免费)
前言 C#/.NET/.NET Core相关技术常见面试题汇总,不仅仅为了面试而学习,更多的是查漏补缺.扩充知识面和大家共同学习.携手进步. 该知识库主要由自己平时学习和工作实践总结.网上优秀文章资料 ...
- 谷歌 Chrome 浏览器离线安装 vue devtools 插件
由于某些原因,Chrome 应用商店访问不了,所以只能离线安装 vue devtools 插件,离线安装也有两种方法. 方法一:自编译 vue devtools 插件 这方法要求动手能力强的同学. 前 ...
- vue学习一(指令2.v-bind,v-model)
2.1.v-bind: 单向绑定(修改数据项,标签内容也改变:修改标签内容,数据项不会改变) 给html标签的属性绑定,可以用来动态修改class,简写 v-bind:style = ...