vuex状态机(vue下一代状态管理Pinia.js 保证你看的明明白白!)
导读:1.pinia的简单介绍 Pinia最初是在2019年11月左右重新设计使用Composition API的 Vue 商店外观的实验。 从那时起,最初的原则相同,但 Pinia 适用于 Vue 2 和 Vue 3 。 并且不需要你使用组合 API。 除了安装和SSR之...
1.pinia的简单介绍
Pinia最初是在2019年11月左右重新设计使用Composition API的 Vue 商店外观的实验 。
从那时起 ,最初的原则相同 ,但 Pinia 适用于 Vue 2 和 Vue 3 。
并且不需要你使用组合 API 。
除了安装和SSR之外 ,还有其他的 API是一样的 。
并且这些针对 Vue 3 ,并在必要时提供 Vue 2 的相关注释 。
以便 Vue 2 和 Vue 3 的用户可以阅读!
2.为什么要使用Pina?
Pinia 是 Vue 的存储库 ,
允许您跨组件/页面共享状态 。
如果您的组合 API ,您可能会认为您可以使用简单的export const state = reactive({})
这对于单页应用程序来说是正确的 ,
但如果它是服务器端的外观 ,将您的应用程序显示给安全漏洞 。
但即使在小型单页应用程序中 ,您也可以从使用 Pinia 中获得好处:
1.开发工具支持
2.动作 、追踪的跟踪
3.热模块更换
4.为 JS 用户提供适当功能的 TypeScript 支持或自动完成
5.服务器端渲染支持
安装
npm install pinia --save
3.创建文件夹和文件-存放数据
在新建 src/store目录并在其下面创建 index.ts文件 ,并导出这个文件
// src/store/index.ts下的代码
import { createPinia } from pinia
const store = createPinia()
export default store
在 main.ts 中引入
import { createApp } from vue
import App from ./App.vue
import router from ./router/index
<!-- 引入 -->
import store from "./store/index"
<!-- 使用store -->
createApp(App).use(router).use(store).mount(#app)
需求描述
假设我们现在有好几个模块 。有user模块 。admin模块 。
我们想对这模块中的数据进行管理 。
为了管理方便 ,后面易于维护 。我们决定将这些模块进行拆分。
于是我们在store下创建 user.ts 文件 ,管理这个user模块的数据 。
user.ts下的数据
//src/store/user.ts 文件
import { defineStore } from pinia
export const useUserStore = defineStore({
id: userkey, // id必填,且需要唯一
// state是存放数据的
state: () => {
return {
name: 于途,
likelist:[],
sex:男,
work:写代码,
heigt:1.70cm
}
},
})
defineStore的介绍
defineStore 接收两个参数.
第一个参数:必须是唯一的 ,多个模块千万千万不能重名 。
因为Pinia 会把所有的模块都挂载到根容器上
第二个参数是一个对象 ,里面的选项state和 Vuex 差不多
4.获取store中值的第一种方法
<template>
<div class="pinia">
<h2> 学习pinia </h2>
<div> {{ userStore }} </div>
<div>姓名:{{ userStore.name }}</div>
<div>性别:{{ userStore.sex }}</div>
<div>工作:{{ userStore.work }}</div>
<div>身高:{{ userStore.heigt }}</div>
</div>
</template>
<script setup lang=ts>
// 引入store中暴露出去的方法
import { useUserStore } from ../../store/user
const userStore = useUserStore()
</script>
获取store中值的第二种方法-computed
<template>
<div class="pinia">
<h2> 学习pinia </h2>
<div>姓名:{{useStoreName}}</div>
<div>性别:{{useStoreSex}}</div>
</div>
</template>
<script setup lang=ts>
// 引入store中暴露出去的方法
import { computed } from vue
import { useUserStore } from ../../store/user
const userStore = useUserStore()
// 使用 computed取获取值
const useStoreName = computed(() => userStore.name)
const useStoreSex = computed(() => userStore.sex)
</script>
提出问题
如果对象上有多个属性,可以进行结构吗?
可以的!
使用 pinia 提供的 storeToRefs
我们来看下怎去使用
5.pinia 提供的 storeToRefs进行结构
<template>
<div class="pinia">
<h2> 学习pinia </h2>
<div>姓名:{{ asName }}</div>
<div>性别:{{ mysex }}</div>
<div>工作:{{ work }}</div>
<div>身高:{{ heigt }}</div>
</div>
</template>
<script setup lang=ts>
import { storeToRefs } from pinia
import { useUserStore } from ../../store/user
const userStore = useUserStore()
// asName 和 mysex 是我取的别名
const { name : asName ,sex:mysex, work, heigt } = storeToRefs(userStore)
</script>
6.如何修改 state 中的数据
修改 state 中的数据 ,可以通过 actions 下的方法。
然后调用 updataName 就可以取修改 state中的name值了
//src/store/user.ts 文件
import { defineStore } from pinia
export const useUserStore = defineStore({
id: userkey, // id必填 ,且需要唯一
// state是存放数据的
state: () => {
return {
name: 于途,
likelist:[],
sex:男,
work:写代码,
heigt:1.70cm
}
},
// actions 可以修改state中的值 ,这里面提供方法
actions:{
// 修改name中的数据
updataName(name:string){
this.name=name
},
},
})
调用方法 ,修改state中的name
<template>
<div class="pinia">
<h2> 学习pinia </h2>
<div>姓名:{{ asName }}</div>
<div>性别:{{ mysex }}</div>
<div>工作:{{ work }}</div>
<div>身高:{{ heigt }}</div>
<el-button type="primary" @click="changeHander">修改name</el-button>
</div>
</template>
<script setup lang=ts>
import { storeToRefs } from pinia
import { useUserStore } from ../../store/user
const userStore = useUserStore()
// asName 和 mysex 是我取的别名
const { name : asName ,sex:mysex, work, heigt } = storeToRefs(userStore)
const changeHander=()=>{
userStore.updataName(小玉兔)
// 这样我发现也可以 ,但是不推荐这样使用 。
// 统一通过 actions 中的方法去修改值
userStore.work=我换工作了
}
</script>
7.getters的使用
//src/store/user.ts 文件
import { defineStore } from pinia
export const useUserStore = defineStore({
id: userkey, // id必填 ,且需要唯一
// state是存放数据的
state: () => {
return {
name: 于途,
likelist:[],
sex:男,
work:写代码,
heigt:1.70cm,
age:26,
}
},
// actions 可以修改state中的值 ,这里面提供方法
actions:{
// 修改name中的数据
updataName(name:string){
this.name=name
},
},
// Getter 完全等同于 Store 状态的计算值
getters:{
// 将姓名进行更改
getName: (state) => {
return state.name + hahha~!
}
}
})
//使用的页面.vue
<template>
<div class="pinia">
<h2> 学习pinia </h2>
<div>姓名:{{ asName }}</div>
<div>性别:{{ mysex }}</div>
<div>工作:{{ work }}</div>
<div>身高:{{ heigt }}</div>
<div>身高:{{ age }}</div>
<!-- 这里就直接使用了getters中的方法 -->
姓名:{{ userStore.getName }}
<el-button type="primary" @click="changeHander">修改name</el-button>
</div>
</template>
<script setup lang=ts>
import { storeToRefs } from pinia
import { useUserStore } from ../../store/user
const userStore = useUserStore()
// asName 和 mysex 是我取的别名
const { name : asName ,sex:mysex,
work, heigt,age
} = storeToRefs(userStore)
const changeHander=()=>{
userStore.updataName(小玉兔)
}
</script>
对于getters的使用的说明
Getter 完全等同于 Store 状态的计算值 computed.
并不会影响原始数据
9.异步actions-设置state中的值
//src/store/user.ts 文件
import { defineStore } from pinia
// 引入接口
import { getUser } from "../https/api";
export const useUserStore = defineStore({
id: userkey, // id必填 ,且需要唯一
// state是存放数据的
state: () => {
return {
name: 于途,
likelist:[],
}
},
// actions 可以修改state中的值 ,这里面提供方法
actions:{
// 修改name中的数据 同步
updataName(name:string){
this.name=name
},
// 异步-获取远端的数据
loadUserList(){
getUser({}).then(res=>{
this.likelist = res
})
}
// 使用await和async 第二种方法
// async loadUserList(){
// const list = await getUser({})
// console.log(list,list)
// this.likelist = list
// }
},
})
使用的页面
<template>
<div class="pinia">
<h2> 学习pinia </h2>
数据 {{ userStore.likelist}}
<el-button type="primary" @click="changeHander">获取远端数据</el-button>
</div>
</template>
<script setup lang=ts>
import { storeToRefs } from pinia
import { useUserStore } from ../../store/user
const userStore = useUserStore()
const changeHander=()=>{
// 异步调用
userStore.loadUserList() // 加载所有数据
}
10.actions 中互相调用方法
很多时候 ,我们可能会出现 actions中互相去调用方法 。
这个时候怎么去处理呢?
通过this.方法名(参数)
//src/store/user.ts 文件
import { defineStore } from pinia
// 引入接口
import { getUser } from "../https/api";
export const useUserStore = defineStore({
id: userkey, // id必填 ,且需要唯一
// state是存放数据的
state: () => {
return {
name: 于途,
likelist:[],
}
},
// actions 可以修改state中的值 ,这里面提供方法
actions:{
// 修改name中的数据 同步
updataName(name:string){
this.name=name
},
// 异步-获取远端的数据
loadUserList(){
getUser({}).then(res=>{
this.likelist = res
this.sayHi(互相调用方法)
})
},
sayHi(mess:string){
console.log(loadUserList方法中调用了sayHi,mess)
}
},
})
使用的页面.vue
<template>
<div class="pinia">
<h2> 学习pinia </h2>
数据 {{ userStore.likelist}}
<el-button type="primary" @click="changeHander">获取远端数据</el-button>
</div>
</template>
<script setup lang=ts>
import { storeToRefs } from pinia
import { useUserStore } from ../../store/user
const userStore = useUserStore()
const changeHander=()=>{
// 异步调用
userStore.loadUserList() // 加载所有数据
}
</script>
11.数据持久化-sessionStorage 或 localStorage
我们都知道,vuex刷新后 ,数据会丢失 。
这个时候我们需要将数据进行持久化 。
我们可以考虑sessionStorage或者localStorage
//src/store/user.ts 文件
import { defineStore } from pinia
// 引入接口
import { getUser } from "../https/api";
export const useUserStore = defineStore({
id: userkey, // id必填 ,且需要唯一
// state是存放数据的
state: () => {
return {
// 数据持久化使用的是sessionStorage
name: sessionStorage.getItem(name) ? sessionStorage.getItem(name) : 于途,
likelist:[],
}
},
actions:{
// 修改name中的数据 同步
updataName(name:string){
sessionStorage.setItem(name, name)
this.name=name
},
},
})
<template>
<div class="pinia">
<h2> 学习pinia </h2>
姓名 {{ userStore.name}}
<el-button type="primary" @click="changeHander">该变值</el-button>
</div>
</template>
<script setup lang=ts>
import { storeToRefs } from pinia
import { useUserStore } from ../../store/user
const userStore = useUserStore()
const changeHander=()=>{
// 异步调用
userStore.updataName(我改变了姓名)
}
</script>
12.跨模块修改数据
虽然我不建议跨模块修改数据 。
因为这样可能会导致你的应用数据流向变得难以理解 。
但是有些时候确实需要跨模块修改数据 。
那么pinia怎么去处理跨模块修数据呢?
下面我们一起来探索跨模块修改数据!
假设admin模块需要去修改user模块中的数据
admin.ts代码如下
//src/store/admin.ts 文件
import { defineStore } from pinia
// 引入user模块
import { useUserStore } from ./user
export const adminUserStore = defineStore({
id: adminkey,
actions:{
// 通过引入的useUserStore模块,然后去触发它里面对应的方法 。
editUserModuleValue(name:string){
// userStore可以看见整个user模块中的数据和方法
let userStore=useUserStore()
console.log(userStore,userStore)
userStore.updataName(name)
}
},
})
user.ts代码
//src/store/user.ts 文件
import { defineStore } from pinia
// 引入接口
export const useUserStore = defineStore({
id: userkey, // id必填 ,且需要唯一
// state是存放数据的
state: () => {
return {
name: 于途,
likelist:[],
sex:男,
work:写代码,
heigt:1.70cm
}
},
actions:{
// 修改name中的数据 同步
updataName(name:string){
this.name=name
},
},
})
页面的使用
<template>
<div class="pinia">
<h2> 学习pinia </h2>
姓名 {{ userStore.name}}
<el-button type="primary" @click="changeHander">该变值</el-button>
</div>
</template>
<script setup lang=ts>
import { storeToRefs } from pinia
// 引入admin模块
import { adminUserStore } from ../../store/admin
// 引入user模块
import { useUserStore } from ../../store/user
const adminStore = adminUserStore()
const userStore = useUserStore()
// dmin模块需要去修改user模块中的数据
const changeHander=()=>{
adminStore.editUserModuleValue(数据数据)
}
</script>
尾声
如果你觉得我写的不错的话 ,可以给我推荐 、打赏 、评论!
上一个给我打赏的小伙伴都已经找到女朋友了!
咦!你不信 ,不信你给我打赏看一下!
保准你追到到喜欢的Ta!
你不会追 ,哎!难受 。
我教你 ,你可以这样说:
小生不才 ,斗胆-问 ,不知姑娘是否心系他人 。
感情之事 ,在下不敢儿戏!
如若姑娘早已心系他人 。那在下便不再打扰 。
如若有所唐突还望姑娘多加体谅!
若姑娘非我良人 ,那在下就不庸人自恼。
在下怕越陷越深 ,还望姑娘尽早告知!话已至此 ,我便先在此谢过!
拿去不谢!回头告诉我结果啊!
咦!抓住一个没有打赏的小伙伴!
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!