面试题答案
一键面试1. 设计状态结构
在Pinia中,我们可以为商品列表和购物车分别定义状态。
// store.js
import { defineStore } from 'pinia'
// 商品列表状态
export const useProductStore = defineStore('product', {
state: () => ({
products: [] as Product[],
// 假设Product类型为 { id: number, name: string, price: number }
})
})
// 购物车状态
export const useCartStore = defineStore('cart', {
state: () => ({
cartItems: [] as CartItem[],
// 假设CartItem类型为 { productId: number, quantity: number }
})
})
2. 定义Actions和Getters
- Actions:用于修改状态的方法。
// 商品列表store的actions
export const useProductStore = defineStore('product', {
state: () => ({
products: [] as Product[]
}),
actions: {
async fetchProducts() {
try {
const response = await fetch('/api/products')
const data = await response.json()
this.products = data
} catch (error) {
console.error('Error fetching products:', error)
}
}
}
})
// 购物车store的actions
export const useCartStore = defineStore('cart', {
state: () => ({
cartItems: [] as CartItem[]
}),
actions: {
addToCart(productId: number) {
const existingItem = this.cartItems.find(item => item.productId === productId)
if (existingItem) {
existingItem.quantity++
} else {
this.cartItems.push({ productId, quantity: 1 })
}
},
removeFromCart(productId: number) {
this.cartItems = this.cartItems.filter(item => item.productId!== productId)
}
}
})
- Getters:用于从状态派生新的数据。
// 购物车store的getters
export const useCartStore = defineStore('cart', {
state: () => ({
cartItems: [] as CartItem[]
}),
getters: {
totalPrice: (state) => {
let total = 0
const productStore = useProductStore()
state.cartItems.forEach(item => {
const product = productStore.products.find(p => p.id === item.productId)
if (product) {
total += product.price * item.quantity
}
})
return total
}
}
})
3. 在组件中使用状态和方法
使用Vue Composition API,通过setup
函数引入Pinia store。
<template>
<div>
<button @click="fetchProducts">Fetch Products</button>
<ul>
<li v-for="product in productStore.products" :key="product.id">
{{ product.name }} - ${{ product.price }}
<button @click="addToCart(product.id)">Add to Cart</button>
</li>
</ul>
</div>
</template>
<script setup lang="ts">
import { useProductStore, useCartStore } from './store'
const productStore = useProductStore()
const cartStore = useCartStore()
const fetchProducts = () => {
productStore.fetchProducts()
}
const addToCart = (productId: number) => {
cartStore.addToCart(productId)
}
</script>
4. 处理跨组件状态共享问题
- 使用Pinia:由于Pinia是一个状态管理库,它本身就支持跨组件状态共享。不同组件只要引入相同的store实例,就可以共享状态。例如,在一个导航栏组件中显示购物车商品数量:
<template>
<div>Cart Items: {{ cartStore.cartItems.length }}</div>
</template>
<script setup lang="ts">
import { useCartStore } from './store'
const cartStore = useCartStore()
</script>
- Provide/Inject:如果需要在组件树中更细粒度地共享状态,可以结合Vue的
provide
和inject
。但一般在使用Pinia后,这种情况较少使用。例如:
<!-- ParentComponent.vue -->
<template>
<div>
<ChildComponent />
</div>
</template>
<script setup lang="ts">
import { provide } from 'vue'
import { useCartStore } from './store'
const cartStore = useCartStore()
provide('cartStore', cartStore)
</script>
<!-- ChildComponent.vue -->
<template>
<div>Cart Total: {{ cartStore.totalPrice }}</div>
</template>
<script setup lang="ts">
import { inject } from 'vue'
const cartStore = inject('cartStore')
</script>