MST
星途 面试题库

面试题:Qwik复杂路径匹配下动态路由参数与数据传递的优化

现有一个电商应用,商品分类页面的路由为/category/:categoryId/sub - category/:subCategoryId,其中sub - category部分是可选的。当访问这个路由时,不仅要获取动态路由参数,还需要根据参数从后端获取相关商品列表数据。请详细说明如何在Qwik中实现此功能,包括如何处理参数的可选性,以及如何优化数据获取以提高页面加载性能。
15.7万 热度难度
前端开发Qwik

知识考点

AI 面试

面试题答案

一键面试
  1. 在Qwik中获取动态路由参数
    • 首先,在Qwik应用中,可以使用useRouteParams钩子来获取动态路由参数。假设在一个组件中实现这个功能,比如CategoryPage.tsx
    import { component$, useRouteParams } from '@builder.io/qwik';
    
    const CategoryPage = component$(() => {
      const { categoryId, subCategoryId } = useRouteParams();
      return (
        <div>
          <p>Category ID: {categoryId}</p>
          {subCategoryId && <p>Sub - Category ID: {subCategoryId}</p>}
        </div>
      );
    });
    
    export default CategoryPage;
    
    • 这里通过useRouteParams获取到categoryIdsubCategoryIdsubCategoryId由于路由中是可选的,所以需要进行存在性检查。
  2. 根据参数从后端获取相关商品列表数据
    • 可以使用useLoader钩子来进行数据获取。useLoader会在服务器端渲染(SSR)和客户端渲染(CSR)时都触发。
    • 假设后端有一个API,比如/api/products?categoryId={categoryId}&subCategoryId={subCategoryId},用于获取商品列表数据。
    import { component$, useLoader, useRouteParams } from '@builder.io/qwik';
    
    const CategoryPage = component$(() => {
      const { categoryId, subCategoryId } = useRouteParams();
      const { data: products, isLoading } = useLoader(() => {
        const url = new URL('/api/products', window.location.origin);
        url.searchParams.append('categoryId', categoryId);
        if (subCategoryId) {
          url.searchParams.append('subCategoryId', subCategoryId);
        }
        return fetch(url.href).then((res) => res.json());
      });
    
      if (isLoading) {
        return <div>Loading...</div>;
      }
    
      return (
        <div>
          <p>Category ID: {categoryId}</p>
          {subCategoryId && <p>Sub - Category ID: {subCategoryId}</p>}
          <ul>
            {products.map((product) => (
              <li key={product.id}>{product.name}</li>
            ))}
          </ul>
        </div>
      );
    });
    
    export default CategoryPage;
    
    • useLoader的回调函数中,构建请求URL,根据subCategoryId是否存在来添加相应的参数,然后使用fetch获取数据。useLoader返回的数据对象包含data(获取到的数据)和isLoading(表示数据是否正在加载)。
  3. 优化数据获取以提高页面加载性能
    • 缓存数据
      • 可以使用浏览器的localStoragesessionStorage来缓存获取到的商品列表数据。在获取数据之前,先检查缓存中是否有对应的数据。
      import { component$, useLoader, useRouteParams } from '@builder.io/qwik';
      
      const CategoryPage = component$(() => {
        const { categoryId, subCategoryId } = useRouteParams();
        const cacheKey = `products_${categoryId}_${subCategoryId || 'all'}`;
        const cachedData = localStorage.getItem(cacheKey);
        const { data: products, isLoading } = useLoader(() => {
          if (cachedData) {
            return Promise.resolve(JSON.parse(cachedData));
          }
          const url = new URL('/api/products', window.location.origin);
          url.searchParams.append('categoryId', categoryId);
          if (subCategoryId) {
            url.searchParams.append('subCategoryId', subCategoryId);
          }
          return fetch(url.href).then((res) => {
            const data = res.json();
            localStorage.setItem(cacheKey, JSON.stringify(data));
            return data;
          });
        });
      
        if (isLoading) {
          return <div>Loading...</div>;
        }
      
        return (
          <div>
            <p>Category ID: {categoryId}</p>
            {subCategoryId && <p>Sub - Category ID: {subCategoryId}</p>}
            <ul>
              {products.map((product) => (
                <li key={product.id}>{product.name}</li>
              ))}
            </ul>
          </div>
        );
      });
      
      export default CategoryPage;
      
    • 服务器端缓存
      • 在后端服务器上,也可以实现缓存机制,比如使用Redis等缓存工具。如果后端接收到相同参数的请求,先检查缓存中是否有数据,有则直接返回缓存数据,减少数据库查询等操作。
    • 代码分割
      • 将数据获取逻辑和组件渲染逻辑进行合理的代码分割。例如,可以将数据获取逻辑封装到一个单独的函数或模块中,这样在组件更新时,如果参数没有变化,就不需要重新执行整个数据获取逻辑。
    • 预加载
      • 在某些情况下,可以在用户可能导航到该页面之前,提前预加载数据。比如在导航栏中,当用户鼠标悬停在商品分类链接上时,使用fetch提前获取相关商品列表数据并缓存起来,当用户真正点击链接进入页面时,直接从缓存中获取数据,提高加载速度。