
vue3——集成Pinia
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负责不同的应用逻辑和数据,使得在大型应用中的管理状态更加清晰。