vue新的状态管理器Pinia

阅读数:129 评论数:0

跳转到新版页面

分类

html/css/js

正文

一、概述

Pinia是为vue开发的一个全新的状态管理器。

1、vuex

State、Getters、Mutations(同步)、Actions(异步)

Vuex4用于vue3

Vue3用于vue2

2、pinia

State、Getters、Actions(同步异步)

即支持vue2也支持vue3。

二、Pinia核心特性

1、没有Mutation

2、Action支持同步和异步

3、没有模块的嵌套结构

pinia通过设计提供扁平结构,就是说每个store都是互相独立的。

4、更好的typescript支持

5、无需手动添加store,它的模块默认情况下创建就自动注册的。

6、支持vue devtools

三、pinia使用

以vue3+typescript为例

1、安装

npm install pinia

2、main.js初始化配置

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')

3、在store目录下创建一个user.ts为例,我们先定义并导出一个名为user的模块

import { defineStore } from 'pinia'
export const userStore = defineStore('user', {
    state: () => {
        return { 
            count: 1,
            arr: []
        }
    },
    getters: { ... },
    actions: { ... }
})

defineStore接收两个参数:

第一个参数是模块的名称,必须是唯一的,pinia会把所有模块都挂载到根容器下。

第二个参数是一个对象,里面的选项和vuex差不多

(1)state用来存储全局状态,使用箭头函数为了更好的ts类型推导

(2)getters 封装计算属性,它有缓存的功能,getters函数的第一个参数是state对象

  // 相当于 vue 中的 computed 计算属性
  getters: {
    // 定义的 getters,第一个参数就是该容器的 state
    comp(state) {
      return ++state.count
    },
    // getter也可以接受其他getter作为第二个参数
    do2(state,otherGetter){
      ...
   }
  },

在pinia中定义常规函数时通过this访问整个store的实例,可以通过this访问其他getter。

在页面组件中可以直接去调用该容器的getters方法

<template>
  <!-- 后面相同的调用,都是基于第一次计算的值 -->
  <p>{{ mainStore.comp }}</p>
  <p>{{ mainStore.comp }}</p>
  <p>{{ mainStore.comp }}</p>
</template>

<script setup lang="ts">
// 导入 pinia 实例
import { useMainStore } from '../store/index'

// 实例化容器
const mainStore = useMainStore()
</script>

<style scoped></style>

(3)actions 封装业务逻辑,修改state

4、访问state

由于defineStore会返回一个函数,所以要先调用拿到的数据对象,然后就可以在模板中直接使用了

<template>
    <div>{{ user_store.count }}</div>
</template>
<script lang="ts" setup>
import { userStore } from '../store'
const user_store = userStore()
// 解构
// const { count } = userStore()
</script>

比如像注释中的解构出来使用,是完全没有问题的,只是注意了,这样拿到的数据不是响应式的,如果要解构还保持响应式就要用到一个方法storeToRefs()

<template>
    <div>{{ count }}</div>
</template>
<script lang="ts" setup>
import { storeToRefs } from 'pinia'
import { userStore } from '../store'
const { count } = storeToRefs(userStore)
</script>

5、更新状态

更新 state 里的数据有四种方法,我们先看三种简单的更新,说明都写在注释里了

<template>
    <div>{{ user_store.count }}</div>
    <button @click="handleClick">按钮</button>
</template>
<script lang="ts" setup>
import { userStore } from '../store'
const user_store = userStore()
const handleClick = () => {
    // 方法一
    user_store.count++
    
    // 方法二,需要修改多个数据,建议用 $patch 批量更新,传入一个对象
    user_store.$patch({
        count: user_store.count1++,
        // arr: user_store.arr.push(1) // 错误
        arr: [ ...user_store.arr, 1 ] // 可以,但是还得把整个数组都拿出来解构,就没必要
    })
    
    // 使用 $patch 性能更优,因为多个数据更新只会更新一次视图
    
    // 方法三,还是$patch,传入函数,第一个参数就是 state
    user_store.$patch( state => {
        state.count++
        state.arr.push(1)
    })
}
</script>

第四种方法就是当逻辑比较多或者请求的时候,我们就可以封装到示例中 store/user.ts 里的 actions 里

可以传参数,也可以通过 this.xx 可以直接获取到 state 里的数据,需要注意的是不能用箭头函数定义 actions,不然就会绑定外部的 this 了

actions: {
    changeState(num: number){ // 不能用箭头函数
        this.count += num
    }
}


// 调用
const handleClick = () => {
    user_store.changeState(1)
}

四、pinia固化插件的使用

https://seb-l.github.io/pinia-plugin-persist/

1、安装依赖

npm i pinia-plugin-persist --save --include=dev
// 或者使用 yarn 安装
yarn add pinia-plugin-persist

2、main.js中

import { createApp } from 'vue'

import App from './App.vue'

import { createPinia } from 'pinia';
// 下面是我们安装的固化插件。
import piniaPersist from 'pinia-plugin-persist'

const app = createApp(App);

const pinia = createPinia();

pinia.use(piniaPersist);

// 特别注意:固化插件是 pinia.use 并不是 app.use

app.use(pinia);

app.mount('#app')

3、在具体的模块中

默认情况下,如果开启(即为true),整个state都会持久化,如果想要部分状态持久化,需要在两个策略中都进行配置。

import { defineStore } from 'pinia';
export const useStore = defineStore('main', {
  state(){
    return {
      count: 10,
      num: 20
    }
  },
  persist: { //  固化插件
    enabled: true, // 开启存储
     strategies: [ // 指定存储的位置以及存储的变量都有哪些,该属性可以不写,
        //在不写的情况下,默认存储到 sessionStorage 里面,默认存储 state 里面的所有数据。
      { storage: localStorage, paths: ["count"] },
      // paths 是一个数组,如果写了 就会只存储 count 变量,当然也可以写多个。
    ]
  },
  getters:{

  },
  
  actions:{
    piniaAdd(){
       this.count++;
    }
  }
})



相关推荐

一、概述 Vuex是一个专门为Vue.js应用程序开发的全局状态管理功能。它采用集中式存储管理应用的所有组件的状态, 并以相应的规则保证状态以一种可预测的方式发生变化。 每一个Vuex应用的核心就是s

一、使用pnpm新建项目 可以使用npm 或yarn或pnpm来初始化Vite项目 pnpm create vite xxx(项目名称) #选择vue #选择js cd xxx (进入项目目录) #安

1、安装依赖 npm install svg-sprite-loader --save-dev 2、配置build文件夹中的webpack.base.conf.js 3、在src/component

在列表渲染时使用key属性 当Vue.js用v-for正在更新已渲染过的元素列表时,它默认用&ldquo;就地复用&rdquo;策略,如果数据项的顺序被改变,Vue将不会移动D

一、vue.js devtools开发工具的使用 1、安装 在chrome或firefox浏览器的扩展插件仓库里搜索vue devtool。 2、debugger的使用 假设我们想调试App.vue这

在一些情况下,我们可能会需要对一个prop进行双向绑定,但它破坏了单向数据流。 在vue 2.3.0,重新引入了.sync修饰符,这是一个语法糖。 例子: <

&lt;div id="app"&gt; &lt;div v-on:click="dodo"&gt;

在登陆页的mouted生命周期方法中,添加 <pre class

ref被用来给元素或子组件注册引用信息,引用信息将会注册在父组件的$refs对象上。如果在普通的DOM元素上使用,引用指向的就是DOM元素,如果用在子组件上,引用就指向组件实例。 <!-- `vm.$

在使用Vue中经常看到HTML中有标签属性前面添加了“:”,有些没有。 其实是v-bind的缩写。 v-bind 缩写: ‘:’ 用法:动态绑定一个或多个特性,或一个组件prop到表达式。在绑定cl