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的兄弟们,来这瞅 ...
随机推荐
- DexExpress Wpf BackstageItemWithImage
参考链接: https://docs.devexpress.com/WPF/DevExpress.Xpf.Ribbon.BackstageItemWithImage.GlyphStyle 设置 Bac ...
- Hive - [08] 数据仓库物理模型设计
分区 分区是将表的数据按照某个列的值进行划分和存储的一种方式.通过分区,可以将数据按照特定的维度进行组织,提高查询效率和数据管理的灵活性. 一.分区的优势 提高查询性能:通过分区,可以将数据按照特定的 ...
- Linux - 禁ping & 开放访问端口
适用于Linux操作系统 禁ping 1.编辑 /etc/sysctl.conf 文件,文件末尾增加如下内容后,保存退出. net.ipv4.icmp_echo_ignore_all = 1 2.在命 ...
- 机器学习 | 强化学习(8) | 探索与开发(Exploration and Exploitation)
8-探索与开发(Exploration and Exploitation) 1.导论 探索与开发二难问题 基于决策的决策过程存在以下两种选择 开发:基于目前的学习做最优的决策 探索:获取更多的学习 最 ...
- Linux系列:如何调试 malloc 的底层源码
一:背景 1. 讲故事 上一篇我们聊过 C# 调用 C 的 malloc 代码来演示heap的内存泄露问题,但要想深入研究得必须把 malloc 的实现库 libc.so 给调试起来,大家都知道在Li ...
- django4.2 与python 最新对应关系表
- Golang 入门 : 变量
变量 Go语言是静态强类型语言,所以变量是有明确类型的.变量实质上就是在内存中的一小块空间,用来存储特定类型的可变数据.如果没有变量我们的程序只能将数值写死都是静态的数据,无法更改,变量可以让我们进行 ...
- linux 上安装portainer.io
inux 上安装portainer.io 1.portainer.io是什么? 2.安装,运行镜像 3.登陆1.portainer.io是什么?Portainer是一个轻量级的Doc ...
- 使用PowerPoint优雅地更改证件照底色
使用PowerPoint优雅地更改证件照底色 首先我们打开一张空白的演示文稿,并将要修改的证件照进行粘贴.(图片来自窝窝摄影,侵删) 选中图片,点击 格式,再点击 删除背景. 点击标记要保留的区域,对 ...
- 获取不到http请求头自定义参数
对外提供的API,需请求方在http请求头中传app_id(下划线分割) 然后服务端通过request.getHeader("app_id")获取不到对应的参数值 排查原因,是因为 ...