MST

星途 面试题库

面试题:Svelte的readable与writable在复杂业务场景下的应用

假设你正在开发一个电商购物车系统,需要使用Svelte的readable和writable来管理商品列表、购物车中商品状态(如数量、选中状态等)以及购物车总价。请详细阐述如何设计状态管理逻辑,包括数据结构、状态更新机制以及如何处理并发操作,比如多个商品同时添加到购物车可能引发的问题。
37.8万 热度难度
前端开发Svelte

知识考点

AI 面试

面试题答案

一键面试

1. 数据结构设计

  • 商品列表数据结构
    • 可以使用一个数组来存储商品列表。每个商品对象包含商品的基本信息,如 id(唯一标识)、name(商品名称)、price(单价)等。
    const productList = [
      { id: 1, name: '商品1', price: 10 },
      { id: 2, name: '商品2', price: 15 }
    ];
    
  • 购物车商品数据结构
    • 同样使用数组存储购物车中的商品。每个购物车商品对象除了包含商品基本信息外,还需要包含 quantity(数量)和 isChecked(选中状态)字段。
    const cartItems = [
      { id: 1, name: '商品1', price: 10, quantity: 1, isChecked: true },
      { id: 2, name: '商品2', price: 15, quantity: 2, isChecked: false }
    ];
    
  • 购物车总价数据结构
    • 使用一个简单的数字变量来表示购物车总价。
    let totalPrice = 0;
    

2. 使用 Svelte 的 readable 和 writable 进行状态管理

  • 引入 Svelte 状态管理工具
    import { writable, readable } from'svelte/store';
    
  • 商品列表状态
    • 使用 readable 存储商品列表,因为商品列表一般不会在运行时被系统内部直接修改(通常是从后端获取后展示)。
    const productListStore = readable(productList);
    
  • 购物车商品状态
    • 使用 writable 存储购物车商品列表,因为购物车中的商品会不断地添加、删除、修改数量和选中状态。
    const cartItemsStore = writable(cartItems);
    
  • 购物车总价状态
    • 使用 writable 存储购物车总价,因为总价会随着购物车商品的变化而变化。
    const totalPriceStore = writable(totalPrice);
    

3. 状态更新机制

  • 添加商品到购物车
    • productListStore 中找到对应的商品,然后在 cartItemsStore 中添加或更新该商品的数量。
    const addToCart = (productId) => {
      cartItemsStore.update((cart) => {
        const existingItem = cart.find((item) => item.id === productId);
        if (existingItem) {
          existingItem.quantity++;
          return cart;
        } else {
          const newItem = productListStore.value.find((product) => product.id === productId);
          newItem.quantity = 1;
          newItem.isChecked = true;
          return [...cart, newItem];
        }
      });
      updateTotalPrice();
    };
    
  • 更新商品数量
    • 直接更新 cartItemsStore 中对应商品的 quantity 字段,并重新计算总价。
    const updateQuantity = (productId, newQuantity) => {
      cartItemsStore.update((cart) => {
        return cart.map((item) => {
          if (item.id === productId) {
            item.quantity = newQuantity;
            return item;
          }
          return item;
        });
      });
      updateTotalPrice();
    };
    
  • 更新商品选中状态
    • 更新 cartItemsStore 中对应商品的 isChecked 字段,并重新计算总价。
    const updateCheckedStatus = (productId, isChecked) => {
      cartItemsStore.update((cart) => {
        return cart.map((item) => {
          if (item.id === productId) {
            item.isChecked = isChecked;
            return item;
          }
          return item;
        });
      });
      updateTotalPrice();
    };
    
  • 计算购物车总价
    • 遍历 cartItemsStore 中选中的商品,计算总价并更新 totalPriceStore
    const updateTotalPrice = () => {
      cartItemsStore.subscribe((cart) => {
        const total = cart.filter((item) => item.isChecked).reduce((acc, item) => acc + item.price * item.quantity, 0);
        totalPriceStore.set(total);
      }).unsubscribe();
    };
    

4. 处理并发操作

  • 使用防抖或节流
    • 对于多个商品同时添加到购物车的操作,可以使用防抖(debounce)或节流(throttle)技术。例如,使用防抖函数,在一定时间内(如 300ms)如果有多次添加操作,只执行最后一次。
    import { onMount } from'svelte';
    let timeout;
    const debounceAddToCart = (productId) => {
      clearTimeout(timeout);
      timeout = setTimeout(() => {
        addToCart(productId);
      }, 300);
    };
    onMount(() => {
      return () => {
        clearTimeout(timeout);
      };
    });
    
  • 使用队列
    • 可以将所有添加商品的操作放入一个队列中,然后按顺序依次处理队列中的任务,避免同时操作 cartItemsStore 引发冲突。
    const addToCartQueue = [];
    const processQueue = () => {
      if (addToCartQueue.length > 0) {
        const productId = addToCartQueue.shift();
        addToCart(productId);
        setTimeout(processQueue, 100); // 控制处理速度
      }
    };
    const addToCartQueueItem = (productId) => {
      addToCartQueue.push(productId);
      if (addToCartQueue.length === 1) {
        processQueue();
      }
    };
    

通过以上设计,可以有效地管理电商购物车系统的状态,并处理可能出现的并发操作问题。