Pinia

pinia

Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。
Pinia 的核心概念包括 state(状态)、getter(获取器)和 action(行为),这些可以类比为组件中的 data、computed 和 methods。Store(如 Pinia)是一个保存状态和业务逻辑的实体,它不与组件树绑定,承载着全局状态。

安装

npm install pinia

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

const pinia = createPinia()
const app = createApp(App)

app.use(pinia)
app.mount('#app')

写法

1、选项式 API: 选项式 API 是一种更接近 Vuex 的写法,其中 defineStore 函数接受一个对象,这个对象包含了 state, actions, getters 等属性。例如:

import { defineStore } from 'pinia';

const useUserStore = defineStore('user', {
  state: () => ({
    name: 'Eduardo',
    age: 24,
  }),
  actions: {
    setName(name) {
      this.name = name;
    },
  },
  getters: {
    fullName: (state) => `${state.name} Doe`,
  },
});

//在组件中使用
import { useUserStore } from '@/stores/user';

export default {
  setup() {
    const userStore = useUserStore();

    // 访问状态
    console.log(userStore.name);

    // 访问 getters
    console.log(userStore.fullName);

    // 调用 actions
    userStore.changeName('John');
  },
};

2、组合式 API: 组合式 API 是 Vue 3 引入的一种新写法,它允许开发者更灵活地组合和重用逻辑。在这种方式中,defineStore 仍然被用来定义 store,但是 storeToRefs 用于将 store 中的响应式状态解构为单独的响应式引用。例如:

import { defineStore } from 'pinia';

const useUserStore = defineStore('user', () => {
  const name = ref('Eduardo');
  const age = ref(24);

  function setName(newName) {
    name.value = newName;
  }
  // 使用 computed 来定义 getters
  const fullName = computed(() => `${name.value} Doe`);
  
  return { name, age, setName };
});

// 在组件中使用
import { useUserStore } from '@/stores/user';

const userStore = useUserStore();

//方法一, 使用 storeToRefs 保持响应性
//const { name, age, setName ,fullName } = storeToRefs(userStore);

//方法二
// 使用 store 的状态和函数
 console.log(userStore.name);
 console.log(userStore.fullName);
 console.log(userStore.age);
 userStore.setName('John');

注意

store 是一个用 reactive 包装的对象,这意味着不需要在 getters 后面写 .value。就像 setup 中的 props 一样,我们不能对它进行解构:
在组件中,你就不需要使用 .value 来访问 name 或 fullName。只有在 store 的内部,当你直接操作 ref 对象时,才需要使用 .value

getter 传递参数

在 Pinia 中,getter 本质上是 Store 状态的派生状态,它们是响应式的计算属性。默认情况下,getter 不接受参数,但你可以通过返回一个函数来绕过这个限制,这样就可以向这个函数传递参数。

import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
  state: () => ({
    users: [
      { id: 1, name: 'Eduardo' },
      { id: 2, name: 'John' },
      // ... 其他用户
    ],
  }),
  getters: {
    getUserById: (state) => {
      // 返回一个函数,该函数接受参数
      return (userId) => {
        // 在函数内部使用参数并返回结果
        return state.users.find((user) => user.id === userId);
      };
     // return (userId) => state.users.find((user) => user.id === userId)
    },
  },
});

在组件中使用时,你可以这样调用这个 getter:

import { useUserStore } from '@/stores/user';

export default {
  setup() {
    const userStore = useUserStore();

    // 获取特定用户
    const user = userStore.getUserById(1);
    console.log(user); // { id: 1, name: 'Eduardo' }

    // 如果需要响应式,可以使用 computed
    const userId = ref(1);
    const specificUser = computed(() => userStore.getUserById(userId.value));
    console.log(specificUser.value); // { id: 1, name: 'Eduardo' }

    // 更改用户 ID
    userId.value = 2;
    console.log(specificUser.value); // { id: 2, name: 'John' }
  },
};

访问其他 store 的 getter

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

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

Action

Action 相当于组件中的 method。它们可以通过 defineStore() 中的 actions 属性来定义,并且它们也是定义业务逻辑的完美选择,action 可以是异步的,你可以在它们里面 await 调用任何 API。

export const useCounterStore = defineStore('main', {
  state: () => ({
    count: 0,
  }),
  actions: {
    increment() {
      this.count++
    },
    randomizeCounter() {
      this.count = Math.round(100 * Math.random())
    },
  },
})

action 异步方法

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)
        // 让表单组件显示错误
        return error
      }
    },
  },
})

访问其他 store 的 action

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')
      }
    },
  },
})
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值