写点什么

Vue3 状态管理 Pinia 快速入门指南

作者:程序员海军
  • 2022 年 7 月 17 日
  • 本文字数:3484 字

    阅读完需:约 11 分钟

Vue3 状态管理 Pinia 快速入门指南

Pinia 状态管理

什么是 Pinia ?

Pinia最初是在 2019 年 11 月左右重新设计使用 Composition API的 Vue Store 外观的实验。从那时起,最初的原则仍然相同,但 Pinia 适用于 Vue 2 和 Vue 3 ,并且不需要你使用组合 API。除了安装SSR 之外,两者的 API 都是相同的,并且这些文档针对 Vue 3 ,并在必要时提供有关 Vue 2 的注释,以便 Vue 2 和 Vue 3 用户可以阅读!

为什么要使用 Pinia?

Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。ç 这对于单页应用程序来说是正确的,但如果它是服务器端呈现的,则会将您的应用程序暴露给安全漏洞。 但即使在小型单页应用程序中,您也可以从使用 Pinia 中获得很多好处:


  • 开发工具支持

  • 跟踪动作、突变的时间表

  • 商店出现在使用它们的组件中

  • 时间旅行和更容易的调试

  • 热模块更换

  • 在不重新加载页面的情况下修改您的商店

  • 在开发时保持任何现有状态

  • 插件:使用插件扩展 Pinia 功能

  • 为 JS 用户提供适当的 TypeScript 支持或自动完成功能

  • 服务器端渲染支持

安装 Pinia

yarn add pinia# or with npmnpm install pinia
复制代码

Pinia 入门

store

可以通过 defineStore() 来定义 store 来存在管理状态,并且它需要一个唯一的名称,作为第一个参数传递:


import { defineStore } from 'pinia'
export const useStore = defineStore('main', { // other options...})
复制代码

使用 store

在组件内导入需要的 store,


注意⚠️:

store`是一个用 包裹的对象`reactive`,这意味着不需要`.value`在 getter 之后编写,但是像`props`in一样`setup

state

定义 state

import { defineStore } from 'pinia'
export const useCounterStore = defineStore({ id: 'haijun', state: () => ({ // 定义状态属性 str: "前端自学社区" }),
})
复制代码

访问 state

通过store 实例来访问


<script setup lang="ts">import {useCounterStore} from '../stores/counter';
const store = useCounterStore()

onMounted(()=> { console.log(store.counter) //访问 state console.log(store.resultCode)})

</script>
复制代码

重制 state

可以通过调用 store 上的方法将状态重置为其初始值:$reset()


const store = useCounterStore()
store.$reset()
复制代码

改变 state

有两种方法


  1. 直接修改 state


   const store = useCounterStore()      store.code++
复制代码


  1. 通过 patch 来修改,一次可修改多个 state


   const store = useCounterStore()      store.$patch((state) => {     state.code = 404     state.counter++     state.carList.push({id:3,name:'奥迪🇦🇹'})   })
复制代码

添加新的 state

有两种方法


  1. 通过 store 的 $state 来赋值一个对象,对象中可以添加多个state


   store.$state = {title: '更换后的store' , author: '海军'}
复制代码


  1. 通过pinia实例来改变 state, 这在SSR 中使用


   pinia.state.value = {}
复制代码

订阅状态

观察状态和变化$subscribe()


<hr/>

Getter

Pinia 中的 getterVuex 中的getter 效果是一样的,接受一个 state 参数,用来访问store 的状态,具有缓存作用


import { defineStore } from 'pinia'
export const useCounterStore = defineStore({ id: 'counter', state: () => ({ counter: 0, code: 200, carList:[ { id:1, name: '特斯拉' }, { id:2, name: '奔驰' } ] }), getters: { doubleCount: (state) => state.counter * 2, resultCode: (state) => state.code + 4, otherGetter(){ return this.resultCode * 4 }, filterIdCarList: (state) => { return (id:number) => state.carList.filter(i => i.id == id) } },
})
复制代码


组件中访问 getter


直接通过store 实例上访问 getter


<template>  <p>Double count is {{ store.doubleCount }}</p></template>
<script setup lang="ts"> import {useCounterStore} from '../stores/counter'; const store = useCounterStore()</script>
复制代码

访问其它 Getter

可以在一个 getter 中访问其它的 getter 与 computer 类似。 它可以组合多个 getter, 可以通过 this 来访问多个 getter


getters: {  doubleCount: (state) => state.counter * 2,  resultCode: (state) => state.code + 4,  // 组合 多个 getter 返回处理结果  otherGetter(){      return this.resultCode * 4 + this.doubleCount * 4  },},
复制代码

参数传递 Getter

getter 本身是用来计算的,本身不可能将参数传递给给它的。但可以通过返回一个函数来接受参数,进行状态处理


getters: {    //第一层传递参数 state, 以便在函数中处理    filterIdCarList: (state) => {      //第二层: 返回一个函数,用来接收传递的参数,进行数据处理      return (id:number) => state.carList.filter(i => i.id == id)    }}
复制代码


组件中使用


<h2>{{filterData(1)}}</h2><!-- [ { "id": 1, "name": "特斯拉" } ]    返回处理的结果-->

<script setup lang="ts">import {useCounterStore} from '../stores/counter';

const store = useCounterStore()const filterData = store.filterIdCarList</script>
复制代码


⚠️⚠️⚠️


通过返回函数后,它不具有缓冲的效果了,它只是调用了该函数。不过可以在 getter 内部做缓存结果。 【不常用】


import { defineStore } from 'pinia'
export const useCounterStore = defineStore({ id: 'counter', state: () => ({ carList:[ { id:1, name: '特斯拉', sell: false }, { id:2, name: '奔驰', sell: true, price: 25 }, { id: 1, name: '奥迪Q5', sell: true, price: 67 } ] }), getters: { getSellCarList: (state) => { //用个变量存储起来 const filterIdCar = state.carList.filter(i => i.sell) return (price: number) => filterIdCar.filter(k => k.price == price) } }})
复制代码

访问其它 store 中的 getter

还可以访问其它 stroe 中的 getter,


导入其它storeimport { useOtherStore } from './other-store'

getters: { otherGetter(state) { const otherStore = useOtherStore //访问其它store 中的state return state.localData + otherStore.data }, },
复制代码

action

它 与 Vuex 中的 Action 是一样的效果,使用也一样。 它可以访问整个store 实例,它是异步的


export const useUsers = defineStore('users', {  state: () => ({    userData: null,    // ...  }),
actions: { async registerUser(login, password) { try { this.userData = await api.post({ login, password }) showTooltip(`Welcome back ${this.userData.name}!`) } catch (error) { return error } }, },})
复制代码


在组件使用 action ,它和 getter 使用一样


<script setup lang="ts">import { useUsers } from '../stores/user';

const store = useUsers()const filterData = store.registerUser('admin','123456')</script>
复制代码

访问其它 store 实例

//user.js


import { defineStore } from 'pinia'

export const useMember = defineStore({ id: 'member', state: () => ({ memberList: [ { id: 111, name: '张飞' }, { id: 222, name: '小红' } ] }), getters: { addMember: (state) => { return (obj:any) => { state.memberList.push(obj) } } }, actions: {
}})
复制代码


import { defineStore } from 'pinia'import {useMember} from './user'// 导入axiosimport axios from 'axios'
export const useCounterStore = defineStore({ id: 'counter', state: () => ({
}), actions: {
async getMenuData(){ const useMembers = useMember() const resultData = await axios.get('http://localhost:3000/menu') //访问其它 store 的 getter state action useMembers.addMember({id:333,name: '老张'}) console.log(useMembers.memberList) } }})
复制代码


最后

欢迎一起交流学习,关注公众公众号:前端自学社区

发布于: 4 小时前阅读数: 14
用户头像

还未添加个人签名 2020.04.02 加入

🏅目前从事物流,铁路相关的前端全栈开发工作. 🏆2021年InfoQ写作平台-签约作者 🏆 🏆微信公众号:【前端自学社区】

评论

发布
暂无评论
Vue3 状态管理 Pinia 快速入门指南_Vue_程序员海军_InfoQ写作社区