1. 集成Pinia

状态管理提供了一种机制,使我们可以在应用的不同部分之间高效地共享和管理状态,而不是将状态散布在多个组件或页面中。

1.1. Pinia基本使用

1.1.1. 使用npm安装Pinia

在项目的根目录下打开终端,执行以下命令。

npm install pinia

1.1.2. 创建Pinia store实例

在main.js中创建并配置Pinia实例。

import { createApp } from 'vue';
import App from './App.vue';
import { createPinia } from 'pinia';
const app = createApp(App);
// 创建Pinia实例
const pinia = createPinia();
app.use(pinia);
app.mount('#app');

在这里,createPinia()用于创建一个新的Pinia实例,然后使用app.use(pinia)将其添加到Vue应用实例中。

一旦Pinia配置完成,就可以开始创建和使用store了。每个store都是一个独立的模块,负责管理应用的一部分状态。

1.1.3. 在项目中创建一个专门的目录如stores

用于组织和管理应用的各种状态。在这个目录下,为每个独立的状态管理创建单独的文件。例如,创建user.js来管理用户信息的状态。

// src/stores/user.js
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
  state: () => {
    return {
      name: 'John Doe',
      age: 30
    };
  },
  actions: {
    updateName(newName) {
      this.name = newName;
    }
  }
});

在这个文件中,defineStore()方法用于定义一个名为user的store。state()方法返回store的状态,这里是name和age。同时定义了updateName这个action,用于更新用户的名称。

1.1.4. 在Vue组件中使用store非常简单

首先导入store,然后就可以访问和修改其中的状态了。示例代码如下。

<script setup>
  import { useUserStore } from '@/stores/user';
const userStore = useUserStore();
console.log(userStore.name); // 输出 'John Doe'
// 更新状态
userStore.updateName('Alice');
console.log(userStore.name); // 输出 'Alice'
</script>

在组件中,通过调用useUserStore来实例化和使用userstore。可以直接访问store中的状态,或者通过调用定义的actions来修改状态。

1.2. 创建和使用store

在Pinia中,store可以看作是管理应用状态的容器,它主要由状态(state)、变更方法(actions)和获取方法(getters)组成。

1.2.1. 状态(state)

状态是store的核心,它包含了应用中需要管理的数据,这些数据可以是用户的信息、应用的配置、UI状态等,例如:

state: () => ({
  username: 'John Doe',
  age: 30,
  isLoggedIn: false
})

在这个示例中,状态包括用户名、年龄和登录状态。这些数据可以在组件中访问和更新。

1.2.2. 变更方法(actions)

actions是定义如何改变状态的方法,可以包含任意异步或同步代码,并且可以调用其他actions或直接改变state,例如:

actions: {
  login() {
    this.isLoggedIn = true;
  },
  logout() {
    this.isLoggedIn = false;
  },
  updateUsername(newUsername) {
    this.username = newUsername;
  }
}

在此示例中,login和logout用于更改用户的登录状态,而updateUsername用于更新用户名。

1.2.3. 获取方法(getters)

getters类似于计算属性,用于基于state派生出新状态。它是响应式的,当依赖的state变化时会自动更新,例如:

getters: {
  info: (state) => {
    return `${state.username} ${state.age}`;
  }
}

在此示例中,info是一个getter,它可以根据用户的username和age拼接用户完整的信息。

一个完整的store代码如下。

import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
  state: () => {
    return {
      username: 'John Doe',
      age: 30,
      isLoggedIn: false
    }
  },
  getters: {
    info: (state) => {
      return `${state.username} ${state.age}`;
    }
  },
  actions: {
    login() {
      this.isLoggedIn = true;
    },
    logout() {
      this.isLoggedIn = false;
    },
    updateUsername(newUsername) {
      this.username = newUsername;
    }
  }
});

在Pinia中,定义getters是可选的。如果store状态比较简单,或者不需要从状态派生出新的状态,则可以选择不定义getters。

在Pinia中,getters主要用于以下两个目的

[插图] 派生状态:当需要从现有状态派生出新的状态时,可以使用getters。例如,一个用户列表,需要从中派生出一个特定年龄段的用户列表,这时getters就非常有用。

[插图] 缓存派生状态:当派生状态的计算成本较高时,使用getters可以有效缓存结果,只有当相关状态改变时,派生状态才会被重新计算。

如果应用状态较为直接,没有复杂的派生逻辑,那么完全可以省略getters。

1.3. 模块化

在Pinia中,模块化是处理大型应用状态的有效方法。通过创建多个独立的store,可以将应用状态分解为更小、更易管理的部分。

每个模块内部可以包含自己的状态、actions和getters,可以专注于管理应用的特定部分,这使得逻辑处理更加集中化。例如,用户信息、产品列表、购物车等。

例如,创建一个管理产品列表的store(product.js),代码如下。

// stores/product.js
import { defineStore } from 'pinia';
export const useProductStore = defineStore('product', {
  state: () => ({
    products: []
  }),
  actions: {
    addProduct(product) {
      this.products.push(product);
    }
  }
});

以上代码中,state中的products数组表示产品列表,actions中的addProduct()方法负责向产品列表添加商品。

创建购物车Store(cart.js),代码如下。

// stores/cart.js
import { defineStore } from 'pinia';
export const useCartStore = defineStore('cart', {
  state: () => ({
    items: []
  }),
  actions: {
    addItem(item) {
      this.items.push(item);
    },
    removeItem(index) {
      this.items.splice(index, 1);
    }
  }
});

以上代码中,state中的items数组表示购物车中的商品,actions中的addItem()与removeItem()方法负责添加和移除商品。

在组件中使用这些store,代码如下。

<script setup>
  import { useProductStore } from '@/stores/product';
import { useCartStore } from '@/stores/cart';
const productStore = useProductStore();
const cartStore = useCartStore();
// 添加产品到产品列表
productStore.addProduct({ id: 1, name: 'Product 1', price: 100 });
// 添加商品到购物车
cartStore.addItem({ productId: 1, quantity: 2 });
</script>

在组件中,可以同时导入和使用多个store,每个store负责不同的应用逻辑和数据,使得在大型应用中的管理状态更加清晰。