Svelte组件props变更不重渲染,如何接收任意数量props?
Svelte子组件接收任意Props并保证响应式的正确方式
问题分析
你遇到的核心问题是:使用$$props一次性解构赋值后,变量不会随$$props更新而响应式变化。初始时options被赋值为空数组,但后续父组件更新options时,子组件里的options变量不会同步更新——因为解构是在组件初始化时执行一次,之后不会自动触发重新解构。
解决方案
针对封装<select>组件这类需要接收任意HTML原生属性+自定义props的场景,推荐两种方式,优先选第一种:
方式1:声明核心响应式Props + 使用$$restProps接收其他Props
这是Svelte官方推荐的最优方案:
- 用
export声明需要单独处理的响应式props(比如你的options),保证它能响应父组件的更新; - 用
$$restProps接收所有未声明的props(比如<select>的原生属性name/disabled等),它会自动保持响应式,且Svelte能对其做优化。
子组件代码示例:
<script lang="ts"> import type { HTMLSelectAttributes } from 'svelte/elements'; type Option = { id: string; value: string; label: string; }; // 声明核心响应式props export let options: Option[] = []; // $$restProps会自动包含所有未用export声明的props,类型自动推导为HTMLSelectAttributes let $$restProps: HTMLSelectAttributes; $: console.log('Child-options', options); </script> <!-- 将$$restProps绑定到select元素,自动传递所有原生属性 --> <select {...$$restProps}> {#each options as option} <option value={option.value}>{option.label}</option> {/each} </select>
方式2:在响应式语句中解构$$props(不推荐,仅特殊场景用)
如果必须完全依赖$$props(比如编译时完全无法预知任何props),需要把解构放在响应式语句中,这样每次$$props变化时都会重新解构:
<script lang="ts"> import type { HTMLSelectAttributes } from 'svelte/elements'; type Option = { id: string; value: string; label: string; }; type $$Props = HTMLSelectAttributes & { options: Option[] }; let options: Option[] = []; let restProps: HTMLSelectAttributes; // 响应式解构:每次$$props变化时重新赋值 $: ({ options, ...restProps } = $$props as $$Props); $: console.log('Child-options', options); </script> <select {...restProps}> {#each options as option} <option value={option.value}>{option.label}</option> {/each} </select>
关键说明
$$restProps是Svelte专门为接收未声明props设计的,性能比$$props更好,因为Svelte可以针对它做编译优化;- 永远不要在组件初始化时一次性解构
$$props,这会丢失响应式——响应式依赖需要通过$:语句或者export声明来建立。
内容的提问来源于stack exchange,提问作者eakl
相关产品推荐
相关产品推荐

