首页 > 其他分享 >Vue3 状态管理之pinia

Vue3 状态管理之pinia

时间:2023-02-28 15:37:01浏览次数:44  
标签:状态 const isCollapse state pinia Vue3 useStore store

什么是Pinia

在vue3之前我们最常用的状态管理就是Vuex,当然在vue3中也有相对应的Vuex的版本。但是还是推荐使用Pinia,原因有以下几点:

  1. 语法简单,mutations 不再存在。
  2. 无需创建自定义复杂包装器来支持 TypeScript,所有内容都是类型化的
  3. 不再需要注入、导入函数、调用函数、享受自动完成功能!
  4. 无需动态添加 Store,默认情况下它们都是动态的
  5. 不再有 modules 的嵌套结构。
  6. 没有 命名空间模块。

Pinia使用

安装

yarn add pinia
# 或者使用 npm
npm install pinia

创建pinia

main.js中创建pinia并挂载。

import { createPinia } from 'pinia'
app.use(createPinia())

定义一个Store

src/store/index.js里引入pinia,并且导出。

Store 是使用 defineStore() 定义的,并且它需要一个唯一名称,作为第一个参数传递:

import { defineStore } from "pinia";

// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id
export const useStore = defineStore('main',{

})

在页面中调用

import {useStore} from "../store/index.js";
const store = useStore()
console.log('store',store)

一旦 store 被实例化,你就可以直接在 store 上访问 stategetters 和 actions 中定义的任何属性。

State

大多数时候,state 是 store 的核心部分。 我们通常从定义应用程序的状态开始。 在 Pinia 中,状态被定义为返回初始状态的函数。 Pinia 在服务器端和客户端都可以工作。

  • 创建state
import { defineStore } from "pinia";

// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id
export const useStore = defineStore('main',{
    // 推荐使用 完整类型推断的箭头函数
    state: () => {
        return {
            // 所有这些属性都将自动推断其类型
            // 定义一个是否展开的字段isCollapse
            isCollapse:false,
            counter: 0,
        }
    }
})
  • 访问 state
<template>
    <p>获取的值:{{store.counter}}</p>
</template>
<script setup>
import {useStore} from "../store/index.js";
const store = useStore()
console.log('store',store.counter)
</script>
  • 重置状态 可以通过调用 store 上的 $reset() 方法将状态 重置 到其初始值:
<template>
    <p>获取的值:{{store.counter}}</p>
    <button @click="reset">重置</button>
</template>
<script setup>
import {useStore} from "../store/index.js";
const store = useStore()
store.counter++
const reset = () => {
  store.$reset()
}
</script>
  • 改变状态 --$patch

除了直接用 store.counter++ 修改 store,你还可以调用 $patch 方法。 它允许您使用部分“state”对象同时应用多个更改:

<template>
   <button @click="open">展开</button>
</template>
<script setup>
import {useStore} from "../store/index.js";
const store = useStore()
const open = () => {
  store.$patch({
    // 修改你要修改的数据
    isCollapse: !store.isCollapse
  })
}
</script>

或者

const open = () => {
  store.$patch( (state) => {
    state.isCollapse = !store.isCollapse
  })
}
  • 改变状态 -- actions

可以在pinia中创建修改方法

import { defineStore } from "pinia";

// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id
export const useStore = defineStore('main',{
    // 推荐使用 完整类型推断的箭头函数
    state: () => {
        return {
            // 所有这些属性都将自动推断其类型
            // 定义一个是否展开的字段isCollapse
            isCollapse: true,
            counter: 0,
        }
    },
    actions: {
        updateCollapse() {
            this.isCollapse = !this.isCollapse
        }
    }

})

在页面调用updateCollapse方法,页面同上就省略多余代码

const open = () => {
  store.updateCollapse()
}
  • 订阅状态

以通过 store 的$subscribe()方法查看状态及其变化,类似于 Vuex 的 subscribe 方法。 与常规的 watch() 相比,使用 $subscribe() 的优点是 subscriptions 只会在 patches 之后触发一次(例如,当使用上面的函数版本时)。

$subscribe 监听store数据修改 当数据改变了 那么subscribe也会触发。

<script setup>
import {useStore} from "../store/index.js";

const store = useStore()
const open = () => {
  store.$patch({
    // 修改你要修改的数据
    isCollapse: !store.isCollapse
  })
}
// 监听store数据修改
let subscribe = store.$subscribe( (params,state) => {
  console.log('params',params)
  console.log('state',state)
  // 每当它发生变化时,将整个状态持久化到本地存储
  localStorage.setItem('collapseState', state.isCollapse)
})
</<script>

getters

Getter 完全等同于 Store 状态的 计算值。 它们可以用defineStore()中的 getters 属性定义。 他们接收“状态”作为第一个参数以鼓励箭头函数的使用:

import { defineStore } from "pinia";

// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id
export const useStore = defineStore('main',{
    // 推荐使用 完整类型推断的箭头函数
    state: () => {
        return {
            // 所有这些属性都将自动推断其类型
            // 定义一个是否展开的字段isCollapse
            isCollapse: false,
            counter: 1,
        }
    },
    getters: {
        // 自动将返回类型推断为数字
        doubleCount: (state) => state.counter * 2,
    },
    actions: {
        updateCollapse() {
            this.isCollapse = !this.isCollapse
        }
    }
})

你可以直接在 store 实例上访问 getter

<p>Double count is {{ store.doubleCount }}</p>
  • 访问其他getter

与计算属性一样,您可以组合多个 getter。 通过 this 访问任何其他 getter

import { defineStore } from "pinia";

// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id
export const useStore = defineStore('main',{
    // 推荐使用 完整类型推断的箭头函数
    state: () => {
        return {
            // 所有这些属性都将自动推断其类型
            // 定义一个是否展开的字段isCollapse
            isCollapse: false,
            counter: 1,
        }
    },
    getters: {
        // 自动将返回类型推断为数字
        doubleCount: (state) => state.counter * 2,
        doubleCountPlusOne() {
            // 自动完成 
            return this.doubleCount + 1
        },
    },
    actions: {
        updateCollapse() {
            this.isCollapse = !this.isCollapse
        }
    }
})
  • 将参数传递给 getterGetters 只是幕后的 computed 属性,因此无法向它们传递任何参数。 但是,您可以从 getter 返回一个函数以接受任何参数:
export const useStore = defineStore('main', {
  getters: {
    getUserById: (state) => {
      return (userId) => state.users.find((user) => user.id === userId)
    },
  },
})

在组价中使用

<script>
export default {
  setup() {
    const store = useStore()

    return { getUserById: store.getUserById }
  },
}
</script>

<template>
  <p>User 2: {{ getUserById(2) }}</p>
</template>
  • 访问其他 Store 的getter
import { useOtherStore } from './other-store'

export const useStore = defineStore('main', {
  state: () => ({
    // ...
  }),
  getters: {
    otherGetter(state) {
      const otherStore = useOtherStore()
      return state.localData + otherStore.data
    },
  },
})

Actions

Actions 相当于组件中的 methods。 它们可以使用 defineStore() 中的 actions 属性定义,并且它们非常适合定义业务逻辑,下面来举个例子:

import { defineStore } from "pinia";

// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id
export const useStore = defineStore('main',{
    // 推荐使用 完整类型推断的箭头函数
    state: () => {
        return {
            // 所有这些属性都将自动推断其类型
            // 定义一个是否展开的字段isCollapse
            isCollapse: false,
            counter: 1,
            userData: null
        }
    },
    getters: {
        // 自动将返回类型推断为数字
        doubleCount: (state) => state.counter * 2,
        doubleCountPlusOne() {
            // 自动完成 
            return this.doubleCount + 1
        },
    },
    actions: {
        updateCollapse() {
            this.isCollapse = !this.isCollapse
        },
         increment() {
            this.counter++
        },
        randomizeCounter() {
            this.counter = Math.round(100 * Math.random())
        },
        // 异步调用
        async registerUser(login,password) {
            try {
                this.userData = await api.post({ login, password})
                console.log(`Welcome back`,this.userData.name)
            } catch (error) {
                return error
            }
        }
    }
})

Actions 在页面上的调用:

import {useStore} from "../store/index.js";

const store = useStore()
const add = () => {
  //store.increment()
  store.randomizeCounter()
}
  • 访问其他 store 操作
import { useAuthStore } from './auth-store'

export const useSettingsStore = defineStore('settings', {
  state: () => ({
    // ...
  }),
  actions: {
    async fetchUserPreferences(preferences) {
      const auth = useAuthStore()
      if (auth.isAuthenticated) {
        this.preferences = await fetchPreferences()
      } else {
        throw new Error('User must be authenticated')
      }
    },
  },
})
  • 订阅 Actions

可以使用 store.$onAction() 订阅 action 及其结果。 传递给它的回调在 action 之前执行。 after 处理 Promise 并允许您在 action 完成后执行函数。

const unsubscribe = someStore.$onAction(
  ({
    name, // action 的名字
    store, // store 实例
    args, // 调用这个 action 的参数
    after, // 在这个 action 执行完毕之后,执行这个函数
    onError, // 在这个 action 抛出异常的时候,执行这个函数
  }) => {
    // 记录开始的时间变量
    const startTime = Date.now()
    // 这将在 `store` 上的操作执行之前触发
    console.log(`Start "${name}" with params [${args.join(', ')}].`)

    // 如果 action 成功并且完全运行后,after 将触发。
    // 它将等待任何返回的 promise
    after((result) => {
      console.log(
        `Finished "${name}" after ${
          Date.now() - startTime
        }ms.\nResult: ${result}.`
      )
    })

    // 如果 action 抛出或返回 Promise.reject ,onError 将触发
    onError((error) => {
      console.warn(
        `Failed "${name}" after ${Date.now() - startTime}ms.\nError: ${error}.`
      )
    })
  }
)

// 手动移除订阅
unsubscribe()

pinia 模块化

pinia中定义模块 只需要定义多个store即可 因为pinia没有单一数据源这个概念 在其中可以定义多个store对象。

<script setup>
// 引用第一个store
import {useCommonStore} from "../store/common"
// 引用第2个store
import {useUserStore} from "../store/user"
let commonStore = useCommonStore()
let userStore = useUserStore()
</script>

标签:状态,const,isCollapse,state,pinia,Vue3,useStore,store
From: https://www.cnblogs.com/stry/p/17164431.html

相关文章

  • vue3+openlayes实现离线地图加载
    概述OpenLayers使在任何网页中放置动态地图变得容易。它可以显示从任何来源加载的地图图块、矢量数据和标记。OpenLayers的开发旨在进一步使用各种地理信息。它是完全免......
  • 学习Pinia
    前言全局状态管理工具Pinia.js有如下特点:完整的ts的支持;足够轻量,压缩后的体积只有1kb左右;去除mutations,只有state,getters,actions;actions支持同步和异步;代码......
  • 研究c#异步操作async await状态机的总结
    研究c#异步操作asyncawait状态机的总结 前言#    前一段时间得闲的时候优化了一下我之前的轮子[DotNetCoreRpc]小框架,其中主要的优化点主要是关于RPC异步契约调......
  • Vue3 + vite + Ts + pinia + 实战
    Pinia起始于2019年11月左右的一次实验,其目的是设计一个拥有组合式API的Vue状态管理库。从那时起,我们就倾向于同时支持Vue2和Vue3,并且不强制要求开发者使用组......
  • vue3中style标签内的一些样式使用
    /*vue3中style标签内的一些样式使用1、使用变量作为css的属性值例如:设置元素的字体大小及字体颜色<scriptsetup>constdata=reactive({fontSize:12,color:"......
  • pinia持久化‘pinia-plugin-persist‘
    Pinia是2019年由vue.js官方成员重新设计的新一代状态管理器,更替Vuex4成为Vuex5。 pinia的优点更好的支持vue3和Tsvuedevtools更好的支持pinia支持服务端渲染支持插......
  • 表格中的状态控制
    //页面初始化加载判断表格行里面审核状态等按钮是否显示  dataLoaded(viewModel){    constgridModel=viewModel.getGridModel();    viewM......
  • vue3 门户网站搭建5-图标
    奈何element自带的图标太少,不够用,故打算使用 vite-plugin-svg-icons组件来封装svg-icon。ps:ui框架选用的 element-ui,为了能跟vue3更好的结合,还得装个 elemen......
  • ABC 291 D - Flip Cards(状态机)
    https://atcoder.jp/contests/abc291/tasks/abc291_d题目大意:n张卡片排成一行。每张卡片正面是数字ai,背面是数字bi。最初,所有的牌都处于正面状态。随机翻转>=0张卡片......
  • 并发多线程学习(五)Java线程的状态及主要转化方法
    1操作系统中的线程状态转换首先我们来看看操作系统中的线程状态转换。在现在的操作系统中,线程是被视为轻量级进程的,所以操作系统线程的状态其实和操作系统进程的状态是......