Pinia vue应用总结

99 阅读3分钟

Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。Pinia 是一个强大而灵活的状态管理库,它的设计目标是让开发者可以更加轻松和高效地管理 Vue.js 应用程序的状态。

安装

yarn add pinia
// # 或者使用 npm
npm install pinia

基本示例

  1. 首先创建一个 Store
// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => {
    return { count: 0 }
  },
  // 也可以定义为
  // state: () => ({ count: 0 })
  actions: {
    increment() {
      this.count++
    },
  },
});

//高级的用例定义一个Store
export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  function increment() {
    count.value++
  }

  return { count, increment }
})
  1. 在组件中使用 Store
import { useCounterStore } from '@/stores/counter'

export default {
  setup() {
    const counter = useCounterStore()

    counter.count++
    // 带自动补全 ✨
    counter.$patch({ count: counter.count + 1 })
    // 或使用 action 代替
    counter.increment()
  },
}

Store

  1. 定义 Store
import { defineStore } from 'pinia'

// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id
export const useStore = defineStore('main', {
  // other options...
})
  1. 使用 store
import { useStore } from '@/stores/counter'

export default {
  setup() {
    const store = useStore()

    return {
      // 您可以返回整个 store 实例以在模板中使用它
      store,
    }
  },
}

State

state 是 store 的核心部分。 我们通常从定义应用程序的状态开始。 在 Pinia 中,状态被定义为返回初始状态的函数。

  1. State
import { defineStore } from 'pinia'

const useStore = defineStore('storeId', {
  // 推荐使用 完整类型推断的箭头函数
  state: () => {
    return {
      // 所有这些属性都将自动推断其类型
      counter: 0,
      name: 'Eduardo',
      isAdmin: true,
    }
  },
})
  1. 访问 state
const store = useStore()
store.counter++; //修改

//重置状态
store.$reset()
  1. 选项 API
import { useStore } from '../stores/counterStore'

export default {
  setup() {
    const store = useStore()

    return { store }
  }
}
  1. 改变状态
store.$patch({
  counter: store.counter + 1,
  name: 'Abalam',
})
  1. 替换state
store.$state = { counter: 666, name: 'Paimon' }

Getters

Getter 完全等同于 Store 状态的 计算值。 它们可以用 defineStore() 中的 getters 属性定义。 与计算属性一样,您可以组合多个 getter。 通过 this 访问任何其他 getter。直接访问任何 getter 作为 store 的属性(与 state 属性完全一样)。

  1. Getter
export const useStore = defineStore('main', {
  state: () => ({
    counter: 0,
  }),
  getters: {
    doubleCount: (state) => state.counter * 2,
  },
})
  1. 在 store 实例上访问 getter
<template>
  <p>Double count is {{ store.doubleCount }}</p>
</template>

<script>
export default {
  setup() {
    const store = useStore()

    return { store }
  },
}
</script>
  1. 将参数传递给 getter
export const useStore = defineStore('main', {
  getters: {
    getUserById: (state) => {
      return (userId) => state.users.find((user) => user.id === userId)
    },
  },
})

//组件中/////////
<script>
export default {
  setup() {
    const store = useStore()

    return { getUserById: store.getUserById }
  },
}
</script>

<template>
  <p>User 2: {{ getUserById(2) }}</p>
</template>
  1. 访问其他 Store 的getter
import { useOtherStore } from './other-store'

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

Actions

Actions 相当于组件中的 methods。

  1. actions
export const useMainStore = defineStore('main', {
  state: () => ({
    counter: 0,
  }),
  actions: {
    increment() {
      this.counter++
    },
    randomizeCounter() {
      this.counter = Math.round(100 * Math.random())
    },
  },
})
  1. 在组件中调用 actions
export default defineComponent({
  setup() {
    const main = useMainStore()
    // Actions 像 methods 一样被调用:
    main.randomizeCounter()

    return {}
  },
})
  1. 访问其他 store 操作
import { useAuthStore } from './auth-store'

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

插件

使用 pinia.use() 将插件添加到 pinia 实例中。 最简单的例子是通过返回一个对象为所有Store添加一个静态属性

import { createPinia } from 'pinia'

// 为安装此插件后创建的每个store添加一个名为 `secret` 的属性
// 这可能在不同的文件中
function SecretPiniaPlugin() {
  return { secret: 'the cake is a lie' }
}

const pinia = createPinia()
// 将插件提供给 pinia
pinia.use(SecretPiniaPlugin)

// 在另一个文件中
const store = useStore()
store.secret // 'the cake is a lie'

Pinia 插件是一个函数,可以选择返回要添加到 store 的属性。 它需要一个可选参数,一个 context:

export function myPiniaPlugin(context) {
  context.pinia // 使用 `createPinia()` 创建的 pinia
  context.app // 使用 `createApp()` 创建的当前应用程序(仅限 Vue 3)
  context.store // 插件正在扩充的 store
  context.options // 定义存储的选项对象传递给`defineStore()`
  // ...
}

pinia.use(myPiniaPlugin)

扩充 store。您可以通过简单地在插件中返回它们的对象来为每个 store 添加属性:

pinia.use(() => ({ hello: 'world' }))

//您也可以直接在 store 上设置属性
pinia.use(({ store }) => {
  store.hello = 'world'
})

//
pinia.use(({ store }) => {
  store.hello = 'world'
  // 确保您的打包器可以处理这个问题。 webpack 和 vite 应该默认这样做
  if (process.env.NODE_ENV === 'development') {
    // 添加您在 store 中设置的任何 keys
    store._customProperties.add('hello')
  }
})

vue3 中 使用pinia

  1. 安装 npm install pinia
  2. 在main.ts文件中导入createPinia函数并将Pinia插件与Vue应用程序绑定

使用 createPinia() 函数创建并初始化Pinia插件实例,将其与Vue应用程序绑定使用app.use(pinia)。至此,我们就可以使用Pinia来管理Vue应用程序的状态了。

import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';

const app = createApp(App);

const pinia = createPinia();
app.use(pinia);

app.mount('#app');
  1. Pinia的核心,Store、State、Getter、Action就不在啰嗦了。
  2. 创建一个Vue组件,并在组件中使用Pinia提供的store。
 const useMovieListStore = defineStore('movie',{ 
  state: () => ({
    isShow: true,
    movies: [],
  }),
  getters: {
    getIsShow() {
      return this.isShow
    },
    getMovies() {
      return this.movies
    },
  },
  actions: {
    setIsShow(value) {
      this.isShow = value
    },
    async fetchMovies() {
      const response = await fetch('https://api.movies.com/movies')
      const data = await response.json()
      this.movies = data
    },
  },
})
export default useMovieListStore;