面试题答案
一键面试1. 性能优化
- 数据处理优化:
- 减少不必要的计算:在实际场景中,比如一个电商购物车组件,当商品数量变化时,需要重新计算总价。可以使用
derived
响应式数据来缓存计算结果,避免每次都重新计算。
<script> import { writable, derived } from'svelte/store'; const cartItems = writable([ { name: '商品1', price: 10, quantity: 1 }, { name: '商品2', price: 20, quantity: 2 } ]); const totalPrice = derived(cartItems, ($cartItems) => { let total = 0; for (let item of $cartItems) { total += item.price * item.quantity; } return total; }); </script> <p>总价: {$totalPrice}</p>
- 防抖与节流:如果组件中有用户频繁触发的操作,如搜索框输入实时搜索。使用防抖或节流来限制触发频率,减少不必要的数据请求。以搜索框为例,使用防抖来处理输入事件。
<script> import { onMount } from'svelte'; import { debounce } from 'lodash'; let searchTerm = ''; const searchResults = []; const performSearch = debounce((term) => { // 实际的搜索逻辑,例如发起 API 请求 console.log(`搜索 ${term}`); }, 300); onMount(() => { const handleInput = (e) => { searchTerm = e.target.value; performSearch(searchTerm); }; document.addEventListener('input', handleInput); return () => { document.removeEventListener('input', handleInput); performSearch.cancel(); }; }); </script> <input type="text" bind:value={searchTerm} placeholder="搜索">
- 减少不必要的计算:在实际场景中,比如一个电商购物车组件,当商品数量变化时,需要重新计算总价。可以使用
- 状态管理优化:
- 合理使用响应式数据:避免过度使用响应式数据导致不必要的重新渲染。比如在一个图片画廊组件中,图片的展示逻辑可能比较复杂,但图片的基本信息(如文件名、尺寸等)不需要频繁更新,这些数据可以定义为普通变量而不是响应式数据。
<script> // 图片基本信息,不是响应式数据 const imageInfo = { filename: 'image1.jpg', width: 800, height: 600 }; let isZoomed = false; // 这里只有 isZoomed 影响图片的显示状态,作为响应式数据 const zoomFactor = isZoomed? 2 : 1; </script> <img src={imageInfo.filename} style="width: {imageInfo.width * zoomFactor}px; height: {imageInfo.height * zoomFactor}px">
2. 可维护性
- 模块化:将复杂逻辑拆分成多个独立的模块。例如,在一个博客文章展示组件中,文章的解析(如 markdown 转 HTML)、评论加载、点赞逻辑等可以分别封装成不同的模块。
- 创建
articleParser.js
模块:
import marked from'marked'; export const parseArticle = (markdown) => { return marked(markdown); };
- 在 Svelte 组件中使用:
<script> import { parseArticle } from './articleParser.js'; let articleMarkdown = '# 文章标题\n这是文章内容'; let articleHtml = parseArticle(articleMarkdown); </script> {@html articleHtml}
- 创建
- 清晰的代码结构:遵循一定的代码规范和约定,例如将变量声明、函数定义、生命周期钩子等按照一定顺序排列。在一个复杂的用户设置组件中:
<script> // 1. 导入 import { writable } from'svelte/store'; // 2. 响应式数据声明 const userSettings = writable({ theme: 'light', fontSize: 16 }); // 3. 函数定义 const changeTheme = (newTheme) => { userSettings.update(settings => { settings.theme = newTheme; return settings; }); }; // 4. 生命周期钩子 import { onMount } from'svelte'; onMount(() => { console.log('组件已挂载'); }); </script> <select bind:value={$userSettings.theme} on:change={(e) => changeTheme(e.target.value)}> <option value="light">亮色主题</option> <option value="dark">暗色主题</option> </select>
3. 可复用性
- 组件化:将通用的逻辑封装成可复用的组件。比如一个通用的按钮组件,其样式、点击事件等可以通过 props 进行配置。
- 创建
Button.svelte
组件:
<script> export let label = '按钮'; export let onClick = () => {}; </script> <button on:click={onClick}> {label} </button>
- 在其他组件中使用:
<script> import Button from './Button.svelte'; const handleClick = () => { console.log('按钮被点击'); }; </script> <Button label="自定义按钮" on:click={handleClick} />
- 创建
- 抽象逻辑:将可复用的逻辑提取出来,比如表单验证逻辑。可以创建一个独立的
formValidator.js
文件,然后在多个表单组件中复用。formValidator.js
:
export const validateEmail = (email) => { const re = /\S+@\S+\.\S+/; return re.test(email); };
- 在表单组件中使用:
<script> import { validateEmail } from './formValidator.js'; let email = ''; let error = ''; const handleSubmit = (e) => { e.preventDefault(); if (!validateEmail(email)) { error = '请输入有效的邮箱'; } else { error = ''; // 提交表单逻辑 } }; </script> <form on:submit={handleSubmit}> <input type="email" bind:value={email} placeholder="邮箱"> {#if error} <p style="color: red">{error}</p> {/if} <button type="submit">提交</button> </form>