插槽传递策略
- 具名插槽优化
- 在多层插槽嵌套时,使用具名插槽可以更清晰地标识不同位置的内容。例如,在一个复杂的布局组件中,可能有页眉、页脚和主体内容等不同部分,通过具名插槽如
header
、footer
、main
来区分,这样在父组件使用时,开发者能更明确地知道每个插槽的用途。
- 实际项目中,在一个通用的页面模板组件里,父组件可以这样使用:
<PageTemplate>
<div slot="header">
<h1>页面标题</h1>
</div>
<div slot="main">
<p>主要内容区域</p>
</div>
<div slot="footer">
<p>版权信息等页脚内容</p>
</div>
</PageTemplate>
- 作用域插槽(Scoped Slots)
- 当子组件需要向插槽传递数据时,作用域插槽非常有用。比如在一个列表组件中,子组件可能需要传递列表项的数据给插槽内的自定义渲染逻辑。
- 例如,在一个商品列表组件中:
<script>
let products = [
{ name: 'Product 1', price: 100 },
{ name: 'Product 2', price: 200 }
];
</script>
<ListComponent>
{#each products as product}
<template let:product>
<div>
<p>{product.name}</p>
<p>价格: {product.price}</p>
</div>
</template>
{/each}
</ListComponent>
- 在
ListComponent
内部,可以通过{#if let:slotContext = $$restProps}
来获取传递给插槽的数据,这样插槽内的内容就可以根据子组件传递的数据进行定制化渲染。
组件状态管理策略
- 集中式状态管理(如使用 Svelte Store)
- 对于大型应用中多层嵌套组件间复杂的数据交互,使用 Svelte Store 进行集中式状态管理可以提升可维护性。例如,在一个电商应用中,购物车状态在多个组件间共享和交互,如商品列表组件、购物车组件、结算组件等。
- 可以创建一个
cartStore
:
// cartStore.js
import { writable } from'svelte/store';
export const cartStore = writable([]);
- 不同组件可以订阅和更新这个状态,比如商品列表组件添加商品到购物车:
<script>
import { cartStore } from './cartStore.js';
let product = { name: 'Sample Product', price: 50 };
function addToCart() {
cartStore.update(cart => {
cart.push(product);
return cart;
});
}
</script>
<button on:click={addToCart}>添加到购物车</button>
<script>
import { cartStore } from './cartStore.js';
let cart;
cartStore.subscribe(value => {
cart = value;
});
</script>
{#each cart as item}
<p>{item.name} - {item.price}</p>
{/each}
- 局部状态封装
- 对于组件自身特有的、不影响其他组件的数据,使用组件内部的局部状态。例如,一个可折叠面板组件,展开和折叠状态是组件自身的行为,不影响其他组件,就可以在组件内部使用局部变量来管理。
<script>
let isOpen = false;
function toggle() {
isOpen =!isOpen;
}
</script>
<button on:click={toggle}>{isOpen? '折叠' : '展开'}</button>
{#if isOpen}
<p>面板内容</p>
{/if}
渲染优化策略
- 基于状态变化的条件渲染
- 避免不必要的渲染,使用
{#if}
等条件语句根据组件状态决定是否渲染某些部分。例如,在一个加载数据的组件中,只有当数据加载完成时才渲染数据展示部分。
<script>
let data;
let isLoading = true;
// 模拟异步数据加载
setTimeout(() => {
data = { message: '加载的数据' };
isLoading = false;
}, 2000);
</script>
{#if isLoading}
<p>加载中...</p>
{:else}
<p>{data.message}</p>
{/if}
- Memoization(记忆化)
- 对于计算属性或函数结果,使用记忆化技术避免重复计算。例如,在一个组件中需要根据多个数据计算一个复杂的结果,可以使用 Svelte 的
$: let memoizedValue = expensiveCalculation();
语法,Svelte 会自动跟踪依赖,只有当依赖数据变化时才重新计算。
<script>
let a = 1;
let b = 2;
function expensiveCalculation() {
// 模拟复杂计算
let result = 0;
for (let i = 0; i < 1000000; i++) {
result += a * b;
}
return result;
}
$: let memoizedValue = expensiveCalculation();
</script>
<p>记忆化结果: {memoizedValue}</p>
- 使用
{#key}
优化列表渲染
- 在渲染列表时,使用
{#key}
指令为每个列表项提供一个唯一的标识,这样 Svelte 可以更高效地更新列表。例如,在一个任务列表组件中,每个任务有唯一的id
:
<script>
let tasks = [
{ id: 1, name: '任务1' },
{ id: 2, name: '任务2' }
];
</script>
{#each tasks as task (task.id)}
<p>{task.name}</p>
{/each}
- 当任务列表发生变化时,Svelte 可以根据
id
更准确地知道哪些项需要更新、添加或删除,而不是重新渲染整个列表。