Svelte:如何强制{#if}块内组件挂载?解决搜索失效问题
解决可折叠侧边栏中未挂载组件的上下文订阅问题
问题核心是Collapsible组件用{#if}控制插槽内容时,未展开状态下插槽内的MyControl会被销毁,无法订阅Sidebar的上下文,导致搜索功能失效。以下是两种可行的解决方法:
方法1:用CSS控制显示隐藏替代{#if}
通过CSS控制内容的显示/隐藏而非销毁组件,让插槽内的MyControl始终保持挂载状态,从而能正常订阅上下文。修改Collapsible.svelte:
<script> import { slide } from 'svelte/transition'; export let expanded = false; </script> <style> .collapsible-wrapper { overflow: hidden; } </style> <div class="collapsible-wrapper"> {#key expanded} {#if expanded} <div transition:slide> <slot /> </div> {:else} <div style="height: 0;"> <slot /> </div> {/if} {/key} </div>
或者更简洁的CSS类方案:
<script> export let expanded = false; </script> <style> .collapsible-content { opacity: 0; height: 0; overflow: hidden; transition: opacity 0.3s, height 0.3s; } .collapsible-content.expanded { opacity: 1; height: auto; } </style> <div class="collapsible-content {expanded ? 'expanded' : ''}"> <slot /> </div>
这样MyControl会始终处于挂载状态,能实时订阅上下文的搜索状态,折叠时也能正常响应搜索。
方法2:将搜索过滤逻辑上移
如果不想始终挂载插槽内容,可以把搜索状态的检查逻辑移到父组件,提前过滤需要显示的MyControl,再传递给Collapsible:
- 在
Sidebar中暴露搜索状态:
<script> import { writable } from 'svelte/store'; export const searchQuery = writable(''); </script> <Searchbar bind:query={$searchQuery} /> <Collapsible> {#each ['hello', 'world'] as label} {#if $searchQuery === '' || label.includes($searchQuery)} <MyControl {label} /> {/if} {/each} </Collapsible>
MyControl无需再订阅上下文,直接接收label即可:
<script> export let label; </script> <!-- 控件内容 -->
这种方式下,父层先处理搜索过滤,Collapsible只渲染符合条件的MyControl,避免了未挂载组件无法订阅的问题。
内容的提问来源于stack exchange,提问作者philr
相关产品推荐
相关产品推荐

