Vue3 中使用 Pinia
Pinia 是一个用于 Vue 3 的状态管理库,能够帮助统一管理应用的状态,并促进组件间的通信。Pinia 提供了 state、getter 和 action,分别对应于组件中的 data、computed 和 methods。
安装
npm install pinia
创建 Store
在 store/xx.js 文件中定义 store:
import { defineStore } from "pinia";
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
actions: {
increment() {
this.count++;
}
},
getters: {
currentCount: (state) => state.count
}
});
注册 Pinia 插件
在 main.js 中引入并使用 Pinia:
import { createPinia } from "pinia";
import { createApp } from "vue";
import App from "./App.vue";
const pinia = createPinia();
createApp(App).use(pinia).mount('#app');
在组件中使用 Pinia
在组件中访问 Pinia 中的数据:
<template>
<h1>计数器</h1>
<p>当前计数: {{ counter.currentCount }}</p>
<button @click="counter.increment">增加</button>
</template>
<script setup>
import { useCounterStore } from "../store/counter";
const counter = useCounterStore();
</script>
使用 Getters
无参数 Getter
按价格过滤书籍示例:
import { defineStore } from "pinia";
export const useBookStore = defineStore("books", {
state: () => ({
list: []
}),
getters: {
expensiveBooks: (state) => state.list.filter(book => book.price > 200)
}
});
在模板中使用:
<template>
<div v-for="book in books.expensiveBooks">
<p>{{ book.title }} - {{ book.price }} - {{ book.publisher }}</p>
</div>
</template>
<script setup>
import { useBookStore } from "../store/books";
import axios from "axios";
const books = useBookStore();
async function fetchBooks() {
try {
const response = await axios.get("http://127.0.0.1:8000/api/books/");
books.list = response.data;
} catch (error) {
console.error(error);
}
}
fetchBooks();
</script>
带参数的 Getter
返回一个函数以实现带参数的 getter:
import { defineStore } from "pinia";
export const useBookStore = defineStore("books", {
state: () => ({
list: []
}),
getters: {
filterBooksByPrice: (state) => (price) => state.list.filter(book => book.price > price)
}
});
在模板中使用带参数的 getter:
<template>
<div v-for="book in books.filterBooksByPrice(minPrice)">
<p>{{ book.title }} - {{ book.price }} - {{ book.publisher }}</p>
</div>
<input type="number" v-model="minPrice" placeholder="最低价格"/>
</template>
<script setup>
import { useBookStore } from "../store/books";
import axios from "axios";
import { ref } from "vue";
const books = useBookStore();
const minPrice = ref(0);
async function fetchBooks() {
try {
const response = await axios.get("http://127.0.0.1:8000/api/books/");
books.list = response.data;
} catch (error) {
console.error(error);
}
}
fetchBooks();
</script>