MST

星途 面试题库

面试题:Svelte状态系统的架构设计与实践

假设要开发一个类似电商购物车的Svelte应用,要求购物车的状态管理使用writable和derived store构建高效状态系统。请阐述整个状态系统的架构设计思路,包括如何划分不同的store,如何处理数据的同步与异步操作,以及如何确保系统的可维护性和扩展性。同时,给出关键部分的代码示例。
29.5万 热度难度
前端开发Svelte

知识考点

AI 面试

面试题答案

一键面试

1. 状态系统架构设计思路

  • 划分不同的store
    • 商品列表store:使用writable来存储购物车中的商品列表。每个商品对象包含商品ID、名称、价格、数量等信息。这样可以方便地对购物车中的商品进行增删改查操作。
    • 总价store:通过derived从商品列表store派生而来。每当商品列表发生变化(添加、删除商品或修改商品数量)时,重新计算总价。这样可以确保总价始终与购物车中的商品状态保持一致,同时避免重复计算,提高效率。
    • 商品数量store:同样使用derived从商品列表store派生,用于快速获取购物车中商品的总数量。
  • 处理数据的同步与异步操作
    • 同步操作:添加商品到购物车、从购物车删除商品、修改商品数量等操作都是同步的。直接修改商品列表store即可,这些修改会立即反映到依赖它的派生store(如总价store、商品数量store)中。
    • 异步操作:例如从服务器加载购物车初始数据,或者将购物车数据保存到服务器。在加载数据时,可以先显示加载状态,待数据加载完成后更新商品列表store。保存数据时,可以在保存成功后更新本地的商品列表store以保持一致性。使用async/await来处理异步操作,确保代码的可读性和顺序性。
  • 确保系统的可维护性和扩展性
    • 模块化:将不同功能的逻辑封装成独立的模块,例如商品操作模块、数据请求模块等。每个模块负责自己的功能,降低模块之间的耦合度。
    • 清晰的接口:为每个store和模块定义清晰的接口,其他部分通过接口来访问和操作数据,这样即使内部实现发生变化,也不会影响到其他部分。
    • 使用类型声明:在Svelte中使用TypeScript,为store的数据结构和函数参数、返回值添加类型声明,提高代码的可维护性和可读性,同时在开发过程中可以利用类型检查发现潜在的错误。

2. 关键部分代码示例

<script lang="ts">
    import { writable, derived } from'svelte/store';

    // 商品列表store
    type Product = {
        id: number;
        name: string;
        price: number;
        quantity: number;
    };
    const cartProducts = writable<Product[]>([]);

    // 总价store
    const totalPrice = derived(cartProducts, ($cartProducts) => {
        return $cartProducts.reduce((acc, product) => acc + product.price * product.quantity, 0);
    });

    // 商品数量store
    const totalQuantity = derived(cartProducts, ($cartProducts) => {
        return $cartProducts.reduce((acc, product) => acc + product.quantity, 0);
    });

    // 同步操作:添加商品到购物车
    const addProductToCart = (product: Product) => {
        cartProducts.update((products) => {
            const existingProduct = products.find(p => p.id === product.id);
            if (existingProduct) {
                existingProduct.quantity++;
                return products;
            } else {
                return [...products, { ...product, quantity: 1 }];
            }
        });
    };

    // 异步操作:从服务器加载购物车数据
    const loadCartData = async () => {
        try {
            const response = await fetch('/api/cart');
            const data: Product[] = await response.json();
            cartProducts.set(data);
        } catch (error) {
            console.error('Error loading cart data:', error);
        }
    };

    // 异步操作:将购物车数据保存到服务器
    const saveCartData = async () => {
        try {
            const response = await fetch('/api/cart', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify($cartProducts)
            });
            if (!response.ok) {
                throw new Error('Failed to save cart data');
            }
        } catch (error) {
            console.error('Error saving cart data:', error);
        }
    };
</script>

{#if $totalQuantity === 0}
    <p>购物车为空</p>
{:else}
    <p>购物车商品数量: {$totalQuantity}</p>
    <p>购物车总价: {$totalPrice}</p>
{/if}

<button on:click={loadCartData}>加载购物车数据</button>
<button on:click={saveCartData}>保存购物车数据</button>