Vue3 Pinia

1.介绍

  • Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态,用来代替vuex
  • 与vuex区别:vuex只有一个store,所有的数据都挂载在其上面,而Pinia是一个管理库,既然是库就可以定义多个store,并单独对他们进行引入

2.安装Pinia

  • 引入pinia
  • 实例化:createPinia()
  • 执行安装:app.use()
import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'

const app = createApp(App)

app.use(createPinia())
app.use(router)

app.mount('#app')

3.定义store

  • 支持定义多个store,以此对数据类型分类,推荐一个文件一个store
  • 每个store包含3个部分:state,getter,action
//store/counter.js
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', () => {
  const count = ref(1)
  const doubleCount = computed(() => count.value * 2)
  function increment() {
    count.value++
  }

  return { count, doubleCount, increment }
})

4.读取store

  • 引入并读取store,可直接修改state,也可以通过action来修改
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter'
const store = useCounterStore()

</script>

<template>
    <main>
        <div>
            <button @click="store.count++">{{ store.count }}</button>
        </div>
        <div>
            <button @click="store.increment()">{{ store.count }}</button>
        </div>
        <h2>{{ store.doubleCount }}</h2>
    </main>
</template>

5.Setup 函数

  • Setup 函数只有在useXXXStore()方法执行时才会运行,且只会运行一次
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter'
//此次才执行Setup 函数中的代码,且只会运行一次(即使此store被多个组件引入也只执行一次)
const store = useCounterStore()
</script>

6.从 Store 解构

  • 每个store是一个具有响应式特性proxy对象,所以能把它的属性和html模版绑定
  • 但是对 Store 解构时,其属性值时一个非响应式的数据,所以不能直接对其进行解构赋值
  • pinia的storeToRefs()可以对store进行转换,将Store的属性转换成ref对象,再包装成对象返回,所以此时解构赋值是可行的
  • 通过storeToRefs()解构赋值的数据和Store的属性指向同一个数据,改变其中的一个,另外一个会受影响
<script setup lang="ts">
import { storeToRefs} from 'pinia'
import { useCounterStore } from '@/stores/counter'

const store = useCounterStore()
const { count } = storeToRefs(store)

console.log('storeToRefs',storeToRefs(store))
console.log('store',store)


</script>

<template>
    <main>
        <div>
            <button @click="count++">{{ count }}</button>
        </div>
        <div>
            <button @click="store.count++">{{ store.count }}</button>
        </div>
    </main>
</template>

7.组合式Store

  • 解析官方案例:为什么store 相互使用时,不能直接在 setup 函数中直接互相读取对方的 state
import { ref } from 'vue'
import { defineStore } from 'pinia'

export const useX = defineStore('x', () => {
    console.log('useX setup')
    const y = useY()

    console.log('useX steup y.name', y.name)
    function doSomething() {
        // ✅ 读取 computed 或 action 中的 y 属性
        const yName = y.name
        // ...
    }

    console.log('useX setup after')
    return {
        name: ref('I am X'),
    }
})

export const useY = defineStore('y', () => {
    console.log('useY setup')
    const x = useX()

    //此时useX的setup还未执行完毕,没有return,拿不到其name
    console.log('useY steup x.name', x.name)
    function doSomething() {
        // ✅ 读取 computed 或 action 中的 x 属性
        const xName = x.name
        // ...
    }

    console.log('useY setup after')
    return {
        name: ref('I am Y'),
    }
})
<script setup lang="ts">
import { useX, useY } from '@/stores/some'

var storeX = useX()
</script>

posted @ 2024-07-10 16:22  ---空白---  阅读(1)  评论(0编辑  收藏  举报