vue3使用pinia管理状态

Pinia

pinia 是一款新的vue3的状态管理库,完整的typescript支持。

安装

yarn add pinia
# or npm
npm install pinia

创建根store并且引用到app上

import { createPinia } from 'pinia'

app.use(createPinia())

定义Store

使用defineStore定义store,第一个参数必须是全局唯一的id,可以使用Symbol

import { defineStore } from 'pinia'

// 第一个参数必须是全局唯一,可以是哟
export const useStore = defineStore('main', {
  
})

使用store

setup中使用useStore创建store实例

<script setup>
import {useStore} from '@/stores/counter'
  
const store = useStore()

....
</script>
  

状态State

定义状态

import { defineStore } from 'pinia',

const useCounterStore = defineStore('counterStore', {
  state: () => ({
    counter: 0
  })
})

定义强状态

import { defineStore } from 'pinia',

interface ICounterStoreState{
  counter: number
}
  
const useCounterStore = defineStore('counterStore', {
  state: ():ICounterStoreState => ({
    counter: 0
  })
})

使用和重置状态

const store = useCounterStore()

// 使用
store.counter++

// 重置
store.$reset()

改变状态

store.$patch({
  counter: store.counter + 1,
  name: 'Abalam',
})

替换状态

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

计算属性Getters

Getter 完全等同于 Store 状态的计算值,可以用 defineStore() 中的 getters 属性定义

export const useStore = defineStore('main', {
  state: () => ({
    counter: 0,
  }),
  getters: {
    doubleCount: (state) => state.counter * 2,
  },
})

传递参数到getters

Getter 是计算属性,也可叫只读属性,因此不可能将任何参数传递给它们。但是可以从 getter 返回一个函数以接受任何参数

export const useStore = defineStore('main', {
  getters: {
    getUserById: (state) => {
      return (userId) => state.users.find((user) => user.id === userId)
    },
  },
})

访问其他store的getters

import { useOtherStore } from './other-store'

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

动作Actions

动作相当于组件中的方法,可以使用 defineStore() 中的 actions 属性来定义,它们非常适合定义业务逻辑

import { mande } from 'mande'

const api = mande('/api/users')

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) {
        showTooltip(error)
        // let the form component display the error
        return error
      }
    },
  },
})

访问其他store的actions

import { useAuthStore } from './auth-store'

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

插件

假设需要在stroe中使用router,就需要使用到pinia的插件机制扩展store的api

pinia.d.ts

import 'pinia'

import { Router} from 'vue-router'

declare module 'pinia' {
  export interface PiniaCustomProperties {
    $router: Router,
  }
}

定义插件

import { createPinia } from 'pinia'
import { App} from "vue";

import { router } from '@/routers'

const pinia = createPinia()
pinia.use(({ store }) => {
    store.$router = router
  })
app.use(pinia)

在action中使用插件定义的pai

import { defineStore } from 'pinia'
import { RouteLocationNormalized } from 'vue-router'
export const useApplicationStore = defineStore('application', {
  state: () => (
    ...
  ),
  actions:{
    toHome(){
      this.$router.push('/home')
    }
  }
})

推荐结构

stores
index.ts
use.store.ts
app.store.ts
...

stores/index.ts

import { createPinia } from 'pinia'
import { App} from "vue";

const pinia = createPinia()

export function setupPinia(app: App){
    pinia.use(({ store }) => {
        ... 这里安装插件
      })
    app.use(pinia)
}

export * from './use.store.ts'
export * from './app.store.ts'

何时使用状态管理器

全局都会使用到的状态使用状态管理器,比如用户信息、主题、权限等等

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容