vue下一代状态管理Pinia.js 保证你看的明明白白!

  • vue下一代状态管理Pinia.js 保证你看的明明白白!已关闭评论
  • 239 次浏览
  • A+
所属分类:Web前端

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> 

vue下一代状态管理Pinia.js 保证你看的明明白白!

获取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> 

vue下一代状态管理Pinia.js 保证你看的明明白白!

提出问题

如果对象上有多个属性,可以进行结构吗? 可以的! 使用 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> 

vue下一代状态管理Pinia.js 保证你看的明明白白!

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> 

vue下一代状态管理Pinia.js 保证你看的明明白白!

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> 

vue下一代状态管理Pinia.js 保证你看的明明白白!

对于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() // 加载所有数据 } 

vue下一代状态管理Pinia.js 保证你看的明明白白!

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> 

vue下一代状态管理Pinia.js 保证你看的明明白白!

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> 

vue下一代状态管理Pinia.js 保证你看的明明白白!

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> 

vue下一代状态管理Pinia.js 保证你看的明明白白!

尾声

如果你觉得我写的不错的话,可以给我推荐、打赏、评论! 上一个给我打赏的小伙伴都已经找到女朋友了! 咦!你不信,不信你给我打赏看一下! 保准你追到到喜欢的Ta! 你不会追,哎!难受。  我教你,你可以这样说: 小生不才,斗胆-问,不知姑娘是否心系他人。 感情之事,在下不敢儿戏! 如若姑娘早已心系他人。那在下便不再打扰。 如若有所唐突还望姑娘多加体谅! 若姑娘非我良人,那在下就不庸人自恼。 在下怕越陷越深,还望姑娘尽早告知!话已至此,我便先在此谢过! 拿去不谢!回头告诉我结果啊! 咦!抓住一个没有打赏的小伙伴!