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


    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!
    你不会追,哎!难受。
    
    我教你,你可以这样说:
    小生不才,斗胆-问,不知姑娘是否心系他人。
    感情之事,在下不敢儿戏!
    如若姑娘早已心系他人。那在下便不再打扰。
    如若有所唐突还望姑娘多加体谅!
    若姑娘非我良人,那在下就不庸人自恼。
    在下怕越陷越深,还望姑娘尽早告知!话已至此,我便先在此谢过!
    拿去不谢!回头告诉我结果啊!
    咦!抓住一个没有打赏的小伙伴!
    
  • 相关阅读:
    NER(HMM实现)
    embedding(keras,word2vec)
    Word2Vec
    nlp文本转化方式小结
    文本向量化(欧氏距离,哈夫曼距离,L1,L2,TF-IDF)
    文件读取与保存(nlp,json)
    python调用大漠插件教程05字库
    Linux重定向与管道
    Linux文件句柄数调整
    HDFS命令实现分析
  • 原文地址:https://www.cnblogs.com/IwishIcould/p/16191212.html
Copyright © 2020-2023  润新知