面试题答案
一键面试实现思路
- 状态管理:在Svelte中,使用响应式变量来存储商品列表数据。当库存数量变化时,更新对应的商品对象的库存属性,Svelte会自动检测到变化并触发视图更新。
- 动画实现:利用CSS的
@keyframes
规则定义缩放和颜色渐变的动画,然后通过Svelte的transition
指令将动画应用到对应的列表项上。 - 性能优化:
- 使用
will-change
属性:在动画开始前告知浏览器元素即将发生变化,让浏览器提前优化。 - 硬件加速:通过
transform
和opacity
属性实现动画,因为这两个属性会触发硬件加速,使动画更流畅。避免使用会导致重排的属性,如width
、height
等。
- 使用
核心代码示例
<script>
let products = [
{ id: 1, price: 100, stock: 5, name: 'Product 1' },
{ id: 2, price: 200, stock: 3, name: 'Product 2' }
];
function updateStock(productId, newStock) {
products = products.map(product => {
if (product.id === productId) {
product.stock = newStock;
}
return product;
});
}
</script>
<style>
@keyframes scaleAndColor {
from {
transform: scale(1);
color: initial;
}
to {
transform: scale(1.2);
color: red;
}
}
li {
will-change: transform, color;
}
.stock-change {
transition: scaleAndColor 0.5s ease;
}
</style>
<ul>
{#each products as product}
<li
class:stock-change={product.stock!== product.stock}
key={product.id}
>
{product.name} - Price: {product.price} - Stock: {product.stock}
<button on:click={() => updateStock(product.id, product.stock - 1)}>
Reduce Stock
</button>
</li>
{/each}
</ul>
处理性能问题
- 避免频繁重绘和重排:如上述提到,使用
transform
和opacity
进行动画,避免修改会触发重排的属性。 - 节流与防抖:如果库存更新操作可能频繁触发,可使用节流(throttle)或防抖(debounce)技术。例如,如果使用防抖,可这样实现:
import { debounce } from 'lodash';
let debouncedUpdateStock = debounce(updateStock, 300);
function handleStockChange(productId, newStock) {
debouncedUpdateStock(productId, newStock);
}
这样可以避免短时间内多次触发库存更新导致性能问题。
- 使用
requestAnimationFrame
:如果动画逻辑较为复杂,可使用requestAnimationFrame
来控制动画的帧率,确保动画流畅运行。例如,可封装一个函数来处理动画更新:
function animateStockChange(productId, newStock) {
requestAnimationFrame(() => {
updateStock(productId, newStock);
});
}
- 优化CSS动画:减少动画关键帧的数量,尽量使用简单的线性动画,避免过度复杂的动画效果。同时,使用
will-change
属性提前告知浏览器元素即将发生的变化,让浏览器有机会提前优化渲染。