Pinia

128 阅读3分钟

Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。

安装: yarn add pinia 或者 npm add pinia

注意,如果是vue2 需要安装 Api : @vue/composition-api

采用了组合式APi 的写法。

import  { createPinia } from "pinia" ; 
Vue.use( createPinia() );

注意,vue2 需要使用下面这种写法

import  { cratePinia , PiniaVuePlugin } from  "pinia" ;
Vue.use(PiniaVuePlugin);
const pinia = createPinia();
new Vue({
  el:'#app',
  ...
  pinia,
})

Store

一个Store 就是一个(pinia)实体,它持有未绑定到组件树的状态和业务逻辑,它托管了全局的状态, 它有点像一个始终存在,并且每个人可以读写的组件。它主要有三个概念,stata , getters 和 actions (数据,计算,方法)。

和Vuex 的区别

去掉了 mutations 。

创建一个 store

defineStore()

import { defineStore } from 'pinia';
// main 应该是应用程序中,store的唯一ID。
export const  useStore  = defineStore('main' , {    // 定义store
  stata:()=>{
    return {
      conunt:1 
    ]  
  ]
})
import {useStore} from "./store/index.ts"
import {ref} from 'vue'
const useList = useStroe()
  console.log(useList.conunt)
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useState = defineStore('main',()=>{ // 定义store
  const state = ref({count:30}) // 定义state
})
import {useStore} from "./store/index.ts"
import {ref} from 'vue'
const useList = useStroe()
console.log(useList.state.count)

使用 store

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

<script setup>
  import  userStore from '@/stotes/counter' // 导入store 所在的文件
  export default {
      const store = useStore(); // 可以根据需要定义任意数量的store变量
      const { name, doubleCount } = store // 会失去响应式
  }
</script>
  • ****可以根据需要定义任意数量的 store ,并且您应该在不同的文件中定义每个 store 以充分利用 pinia
  • store 返回的是一个用reactive 包裹的对象,所以,不可以对 store 直接进行解构,会失去数据的响应式 。
  • 如果想从store 中取值,并且保持响应式,需要使用 storeToRefs()
<script setup>
  import { storeToRefs } from 'pinia' ;
  export default {
    // 会保持响应式 , 这也会为插件添加的属性创建引用
    // 但跳过任何 action 或 非响应式(不是 ref/reactive)的属性
    const { naem , doubleCount } = storeToRefs ( store ) 
  }
</script>

state

state 是 store 的核心内容,它定义了应用程序的初始状态,是一个Function。

import { defineStore } from 'pinia'
const useStore = defineStore('storeId',{
      stete :()=>{
        return {
          // ... 初始值,例如 name : '小明'
        }
      }
})

使用stata

// Example File Path:
// ./src/stores/counterStore.js

import { defineStore } from 'pinia',

const useCounterStore = defineStore('counterStore', {
  state: () => ({
    counter: 0
  })
})
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useState = defineStore('main',()=>{ // 定义store
  const state = ref({count:30}) // 定义state
  return{state}
})
<!-- 使用 store 和 state -->
<script >
  import { useCounterStore } from '../stores/counterStore' 
  // 在组件内部引入 store  即可使用state中定义的属性
  export default {
      const counterStore = useCounterStore()  
      computed: {
      	tripleCounter() {
        	return counterStore.counter * 3
      	},
    	},
  }
</script>

修改state的值还可以使用 $patch () $patch 的参数可以是对象,也可以是Fuction,

store.$patch((state) => {
  state.items.push({ name: 'shoes', quantity: 1 })
  state.hasChanged = true
})

替换 state

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,
  },
})
import { defineStore } from 'pinia';
import { ref , computed } from 'vue';
export const useState = defineStore('main',()=>{ // 定义store
  const state = ref({count:30}) // 定义state
  const getState = Computed(()=>{
    return state.count.value ++
  })
  rutern {state , getState}
})

大多数时候,getter 只会依赖状态,但是,他们可能需要使用其他 getter。 正因为如此,我们可以在定义常规函数时通过 this 访问到整个 store 的实例

export const useStore = defineStore('main', {
  state: () => ({
    counter: 0,
  }),
  getters: {
    // 自动将返回类型推断为数字
    doubleCount(state) {
      return state.counter * 2
    },
    // 返回类型必须明确设置
    doublePlusOne(): number {
      return this.counter * 2 + 1
    },
  },
})

在组件中导入store 后,可以直接访问store 中定义的 getters。

Actions

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

actions 支持 同步和异步,可以通过this访问state中定义的值

export const useStore = defineStore('main', {
  state: () => ({
    counter: 0,
  }),
  actions: {
    increment() {
      this.counter++
    },
    randomizeCounter() {
      this.counter = Math.round(100 * Math.random())
    },
  },
})
import { defineStore } from 'pinia';
import { ref , computed } from 'vue';
export const useState = defineStore('main',()=>{ // 定义store
  const state = ref({count:30}) // 定义state
  const getState = Computed(()=>{
    return state.value.count. ++
  })
  function test (){
    console.log(state.value)
  }
  rutern {state , getState ,test}
})