• Pinia实操配置,Vuex的替代品


    技术更新迭代快,学习要永不停步!

    什么是Pinia?

    在这里插入图片描述
    就是这个菠萝(一种美味的热带水果)

    Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态;
    Pinia 最初是为了探索 Vuex 的下一次迭代会是什么样子,结合了 Vuex 5 核心团队讨论中的许多想法。最终,意识到 Pinia 已经实现了我们在 Vuex 5 中想要的大部分内容,并决定实现它 取而代之的是新的建议。

    现在官方网站的生态推荐已经将Vuex换成了Pinia
    
    • 1

    与Vuex相比的优势

    与 Vuex 相比,Pinia 提供了一个更简单的 API,具有更少的仪式,提供了 Composition-API 风格的 API,最重要的是,在与 TypeScript 一起使用时具有可靠的类型推断支持。
    总结以下五点:

    1. 可以对Vue2和Vue3做到很好的支持,也就是老项目也可以使用Pinia。
    2. 抛弃了Mutations的操作,只有state、getters和actions.极大的简化了状态管理库的使用,让代码编写更加容易直观。
    3. 不需要嵌套模块,符合Vue3的Composition api ,让代码更加扁平化。
    4. 完整的TypeScript支持。Vue3版本的一大优势就是对TypeScript的支持,所以Pinia也做到了完整的支持。如果你对Vuex很熟悉的化,一定知道Vuex对TS的语法支持不是完整的(经常被吐槽)。
    5. 代码更加简洁,可以实现很好的代码自动分割。Vue2的时代,写代码需要来回翻滚屏幕屏幕找变量,非常的麻烦,Vue3的Composition api完美了解决这个问题。 可以实现代码自动分割,pinia也同样继承了这个优点。

    创建store并使用

    1. 搭建项目并安装Pinia

    项目搭建不再赘述
    执行安装Pinia

    yarn add pinia
    // or
    npm i pinia
    
    • 1
    • 2
    • 3

    2. 创建一个store

    1、首先在main.js中引入pinia

    import { createApp } from 'vue'
    import App from './App.vue'
    import { createPinia } from 'pinia'//创建一个 pinia(根存储)并将其传递给应用程序:
    createApp(App).use(createPinia()).mount('#app')
    
    • 1
    • 2
    • 3
    • 4

    2、在src目录下创建一个store文件夹,并新建index.js,写入以下内容:

    import { defineStore } from 'pinia'
    
    // useStore 可以是 useUser、useCart 之类的任何东西
    // 第一个参数是应用程序中 store 的唯一 id
    export const useStore = defineStore('main', {
      // other options...
      state: () => {
        return {
          msg: 'hello world!',
          count: 0
        }
      },
      getters: {},
      actions: {}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    defineStore()	定义Store,并且它需要一个唯一名称,作为第一个参数传递
    参数:
    第一个参数:相当于为容器起一个名字。注意:这里的名字必须唯一,不能重复。
    第二个参数:一个配置对象,里边是对容器仓库的配置说明。
    	state 属性: 用来存储全局的状态的
    	getters属性: 类似计算属性,用来监视或者说是计算状态的变化的,有缓存的功能。
    	actions属性: 修改state,对state里数据变化的业务逻辑,需求不同,编写逻辑不同。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3、在组件中使用

    两种方法
    第一种:之间使用整个store取值
    第二种:结构取值,但不要直接结构store

    storeToRefs:为了从 Store 中提取属性同时保持其响应式, 它将为任何响应式属性创建 refs
    
    • 1

    示例:

    <template>
      <div>{{ store.msg }}div>
      <div>{{ msg }}div>
    template>
    
    <script setup>
    import { useStore } from '@/store/index';
    import { storeToRefs } from "pinia";
    let store = useStore()
    // 不要直接结构,会破坏响应式,使用storeToRefs
    // const { msg } = store;
    const { msg } = storeToRefs(store);
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    修改store

    修改方法有5种

    1. 直接修改

    <template>
      <div>{{ store.count }}div>
      <button @click="add">+1button>
    template>
    
    <script setup>
    import { useStore } from '@/store/index';
    let store = useStore()
    const add = () => {
      store.count++
    }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2. 调用$patch

    这个方法可以修改多个状态

    <template>
      <div>{{ store.count }}div>
      <button @click="add">+1button>
    template>
    
    <script setup>
    import { useStore } from '@/store/index';
    let store = useStore()
    const add = () => {
      store.$patch({
        count: store.count + 1,
        msg: 'hello pinia!'
      })
    }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    $patch与直接进行两次修改的好处在哪里?
    
    Pinia的官方网站,已经明确表示$patch的方式是经过优化的,会加快修改速度,对程序的性能有很大的好处。
    所以如果你是多条数据同时更新状态数据,推荐使用$patch方式更新。
    
    • 1
    • 2
    • 3
    • 4

    3. $patch加函数的形式修改状态数据

    这种方法适合复杂数据的修改,比如数组、对象的修改,因为它们的修改非常困难或代价高昂

    首先我们在useStore中增加一个数组一个对象

    import { defineStore } from 'pinia'
    
    export const useStore = defineStore('main', {
      state: () => {
        return {
          msg: 'hello world!',
          count: 0,
          userInfo: {
            name:'张三'
          },
          userItems: []
        }
      },
      getters: {},
      actions: {}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    然后执行修改

    const add = () => {
      store.$patch((state) => {
        state.userItems.push({ name: 'shoes', quantity: 1 }),
        state.userInfo.name = '李四'
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4. 替换state

    可以通过将其 $state 属性设置为新对象来替换 Store 的整个状态:

    store.$state = { counter: 666, name: 'Paimon' }
    
    • 1

    5. 通过action修改

    当逻辑复杂,不直接进行修改,那就用action

    首先在useStore中添加action

      actions: {
        changeCount() {
          // 通过this取值改值,所以不要使用箭头函数
          this.count++
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后进行使用

    const add = () => {
      store.changeCount()
    }
    
    • 1
    • 2
    • 3

    6. 重置store

    可以通过调用 store 上的 方法将状态 重置 到其初始值

    const store = useStore()
    store.$reset()
    
    • 1
    • 2

    getters的使用

    首先添加

      getters: {
        tenCount(){
          return this.count*10
        }
        // 这种方便ts进行类型推断
        // tenCount(state){
        //   return state.count*10
        // }
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用

    <div>{{ store.tenCount }}div>
    
    • 1

    store间互相调用

    在这里插入图片描述
    Pinia不再有modules的嵌套结构
    所以你可以灵活使用每一个store,它们是通过扁平化的方式来相互使用的;

    首先在store文件夹中创建user.js,写入以下内容:

    import { defineStore } from 'pinia'
    
    export const useUser = defineStore('user', {
        state: () => {
            return {
                name: '张三'
            }
        }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    接下来在useStore中调用

    import { defineStore } from 'pinia'
    import { useUser } from './user';// 导入useUser
    export const useStore = defineStore('main', {
      state: () => {
        return {
          msg: 'hello world!',
          count: 0
        }
      },
      getters: {
        getUser() {
          return useUser().name;// 取值
        }
      },
      actions: {}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    最后你就可以在组件中去调用getUser了

    数据持久化

    使用pinia-plugin-persist插件实现数据持久化

    1、 安装

    npm i pinia-plugin-persist
    
    • 1

    2、 在main.js中引入

    import { createApp } from 'vue'
    import App from './App.vue'
    import { createPinia } from 'pinia'
    import piniaPersist from 'pinia-plugin-persist'
    
    let pinia = createPinia()
    pinia.use(piniaPersist)
    
    createApp(App).use(pinia).mount('#app')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3、 在store中配置

    import { defineStore } from 'pinia'
    import { useUser } from './user';// 导入useUser
    export const useStore = defineStore('main', {
      state: () => {
        return {
          msg: 'hello world!',
          count: 0
        }
      },
      getters: {
        getUser() {
          return useUser().name;// 取值
        }
      },
      actions: {},
      persist: {
        enabled: true, // 开启缓存  默认会存储在本地localstorage
        storage: sessionStorage, // 缓存使用方式
        paths:[] // 需要缓存键 
      }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    这样数据就可以实时的存储到storage中

  • 相关阅读:
    组件安全以及漏洞复现
    HTML网页大作业代码【免费代码已上传】
    Apriori算法
    C++ 继承和派生 万字长文超详解
    一站式服务:教你搭建AI知识库
    线性筛的简单证明
    SpringBoot-31-springboot整合shiro
    分布式(一致性协议)之领导人选举( DotNext.Net.Cluster 实现Raft 选举 )
    二十种实战调优MySQL性能优化的经验
    3DMax
  • 原文地址:https://blog.csdn.net/lhkuxia/article/details/126678790