全局状态管理库Pinia

296 阅读1分钟

在 Vue 和 React 中,实现组件间的通信

1、Vue中,props + 事件emit (父子组件之间)

2、Vue中,provide + inject (爷孙或者远房亲戚之间)

3、React中,context + useContext

Vue3 中, 可以使用全局状态管理 store

import { reactive } from 'vue'
import { defineComponent } from 'vue'

const store = reactive({
  me: {
    id: 1,
    name: 'HXL',
  },
})

export const ChildOne = defineComponent({
  setup: (props, context) => {
    return () => (
      <div>
        <span>hi,</span>
        {store.me.name}
      </div>
    )
  },
})

export const ChildTwo = defineComponent({
  setup: (props, context) => {
    return () => (
      <div>
        <input v-model={store.me.name} />
      </div>
    )
  },
})

但是上面的全局状态管理 store 有个 BUG

就是跨请求状态污染

在上面的全局状态管理中,所有用户的 store 是公用的,在浏览器中是可以使用的,因为对于浏览器的每一个页面访问,store 会重新初始化。

但是,SSR 环境下,sotre 只在服务器启动时初始化一次。store 会在多个服务器之间复用,如果某一个用户发请求对 store 中的重要数据进行修改,那么这个数据会意外的泄露给另一个用户的请求。这就是跨请求状态污染。

所以可以在 Vue 中使用 Pinia 可以解决该问题,在 React 中使用 Zustand

在 Pinia 中,每一个 App 都会有自己的 Pinia ,不会污染。

使用方法:

  1. pnpm i pinia
  2. main.ts中
const pinia = createPinia()
app.use(pinia)
  1. 组件中
const useStore = defineStore('store', {
  state() {
    return {
      me: {
        name: 'HXL',
      },
    }
  },
  actions: {
    refetchMe() {
      this.me.name = 'xxx'
      axios().then(() => {
        this.me
      })
    },
  },
})

export const ChildOne = defineComponent({
  setup: (props, context) => {
    const store =useStore()
    return () => (
      <div>
        <span>hi,</span>
        {store.me.name}
      </div>
    )
  },
})

export const ChildTwo = defineComponent({
  setup: (props, context) => {
    const store =useStore()
    return () => (
      <div>
        <input v-model={store.me.name} />
      </div>
    )
  },
})