面试题答案
一键面试优化derived计算属性的依赖关系
- 减少不必要依赖:
- 仔细分析derived计算属性所依赖的Store。只将真正影响计算结果的Store作为依赖传入。例如,假设我们有一个购物车应用,有一个
cartStore
存储购物车商品列表,一个userSettingsStore
存储用户的一些设置(如语言偏好等)。如果一个计算属性totalPrice
只是用于计算购物车商品的总价,它只应依赖cartStore
,而不应依赖userSettingsStore
。 - 在Svelte中代码示例如下:
- 仔细分析derived计算属性所依赖的Store。只将真正影响计算结果的Store作为依赖传入。例如,假设我们有一个购物车应用,有一个
import { writable, derived } from'svelte/store';
const cartStore = writable([]);
// 这里userSettingsStore与总价计算无关,不应该作为依赖
// const userSettingsStore = writable({language: 'en'});
const totalPrice = derived(cartStore, ($cart) => {
let total = 0;
$cart.forEach(item => {
total += item.price * item.quantity;
});
return total;
});
- 深度依赖处理:
- 当Store中的数据结构较为复杂时,要注意依赖的深度。例如,如果一个Store存储了一个对象,对象内部有多个属性,而计算属性只依赖其中某个属性的变化。在这种情况下,直接将整个对象作为依赖可能会导致不必要的重新计算。
- 可以通过使用Svelte的
get
函数获取Store值,并只监听相关属性变化。例如:
import { writable, derived, get } from'svelte/store';
const complexStore = writable({
data1: { subData1: 'value1', subData2: 'value2' },
data2: 'otherValue'
});
const relevantData = derived(complexStore, ($complexStore) => {
return $complexStore.data1.subData1;
});
// 更好的方式是,当subData1变化时才重新计算
const betterRelevantData = derived(() => get(complexStore).data1.subData1, (subData1) => {
return subData1;
});
缓存策略
- 手动缓存:
- 可以在计算属性内部实现一个简单的缓存机制。例如,记录上一次计算的结果和依赖值,只有当依赖值发生变化时才重新计算。
- 以下是一个简单示例:
import { writable, derived } from'svelte/store';
const inputStore = writable(0);
let lastInput = null;
let cachedResult = null;
const cachedComputed = derived(inputStore, ($input) => {
if (lastInput === $input) {
return cachedResult;
}
lastInput = $input;
cachedResult = $input * 2; // 这里是简单的计算示例
return cachedResult;
});
- 使用Memoization库:
- 对于更复杂的场景,可以使用一些外部库来实现更强大的记忆化(缓存)功能。例如,
lodash
库中的memoize
函数。虽然lodash
不是专门为Svelte设计的,但可以与Svelte结合使用。 - 示例如下:
- 对于更复杂的场景,可以使用一些外部库来实现更强大的记忆化(缓存)功能。例如,
import { writable, derived } from'svelte/store';
import { memoize } from 'lodash';
const inputStore = writable(0);
const expensiveCalculation = memoize((input) => {
// 这里模拟一个复杂的计算
let result = 0;
for (let i = 0; i < input * 1000; i++) {
result += i;
}
return result;
});
const memoizedComputed = derived(inputStore, ($input) => {
return expensiveCalculation($input);
});
在复杂数据依赖场景下避免不必要重新计算
假设我们有一个复杂的电商应用,有多个Store。productStore
存储商品信息,cartStore
存储购物车商品列表,userLocationStore
存储用户的地理位置,promotionStore
存储促销活动信息。我们要计算购物车商品的最终价格,这个价格可能会受到商品原价(来自productStore
)、购物车中商品数量(来自cartStore
)、用户所在地区的促销活动(来自promotionStore
根据userLocationStore
判断)的影响。
import { writable, derived } from'svelte/store';
const productStore = writable([
{ id: 1, name: 'Product 1', price: 10 },
{ id: 2, name: 'Product 2', price: 20 }
]);
const cartStore = writable([
{ productId: 1, quantity: 2 },
{ productId: 2, quantity: 1 }
]);
const userLocationStore = writable('region1');
const promotionStore = writable({
region1: { discount: 0.1 },
region2: { discount: 0.2 }
});
// 优化前,依赖所有Store,可能导致不必要重新计算
// const totalPrice = derived([productStore, cartStore, userLocationStore, promotionStore], ([$products, $cart, $location, $promotions]) => {
// let total = 0;
// $cart.forEach(cartItem => {
// const product = $products.find(p => p.id === cartItem.productId);
// if (product) {
// const promotion = $promotions[$location];
// const discountedPrice = product.price * (1 - (promotion? promotion.discount : 0));
// total += discountedPrice * cartItem.quantity;
// }
// });
// return total;
// });
// 优化后,只依赖真正影响计算的部分
const relevantCartInfo = derived(cartStore, ($cart) => {
return $cart.map(cartItem => ({ productId: cartItem.productId, quantity: cartItem.quantity }));
});
const relevantPromotion = derived([userLocationStore, promotionStore], ([$location, $promotions]) => {
return $promotions[$location];
});
const totalPrice = derived([productStore, relevantCartInfo, relevantPromotion], ([$products, $cartInfo, $promotion]) => {
let total = 0;
$cartInfo.forEach(cartItem => {
const product = $products.find(p => p.id === cartItem.productId);
if (product) {
const discountedPrice = product.price * (1 - ($promotion? $promotion.discount : 0));
total += discountedPrice * cartItem.quantity;
}
});
return total;
});
通过这种方式,将复杂的依赖关系进行拆分和优化,只在真正影响计算结果的部分发生变化时才重新计算totalPrice
,避免了不必要的重新计算,提高了应用性能。