Ужасно простая реализация дерева со сверхспособностями Svelte.
Дерево имеет видимую глубину, текстовый фильтр и функции переключения, написанные настолько лаконично и масштабируемо, насколько это возможно в Svelte.
Итак, у нас есть следующие компоненты:
- tree - just wrapping it all together - root - to allow multiple roots in a tree - node - a svelte:self component that iterates itself - open - svg for open arrow - closed - svg for closed arrow - store.js - a store to hold keyword results for any use (e.g count)
корень
- предоставить входные данные для дерева фильтров
- передать данные узлу и сообщить узлу, что это корень
- передать visibleDepth, чтобы проверить, должен ли узел быть видимым
<input type=range bind:value={visibleDepth} min=1 max={4}> {visibleDepth} <input type=text bind:value={text}/> {$results.length} <ul> {#if visibleDepth} <Node bind:node={data} {visibleDepth} {text} root/> {/if} </ul>
узел
начнем с разметки, далее скрипт
- обернуть по логике отображения
- нажмите, чтобы переключить
- стиль, если он соответствует фильтру
- если он открыт и имеет дочерние элементы, повторяющие компонент
{#if !text || visible || childVisible || root} <li on:click={toggle} style="padding-left:{level*1}rem" transition:slide> <svelte:component this={state}/> <!-- arrow --> <span style={visible ? 'color: red':''}>{level}: {node.data</span> </li> {/if} {#if state === Open && node.children} {#each node.children as child} <svelte:self node={child} {visibleDepth} {text} level={level+1} bind:visible={childVisible}/> {/each} {/if}
вот его скриптовая часть
- функция фильтрации по вводу текста
- передать в магазин, если элемент соответствует
- проверить, какую стрелку отображать — отфильтрованную или нет
- рассчитать, видны ли
- сбросить хранилище результатов, если фильтр не указан
const filtered = (item) => { let match = text.length === 0 || item.data.toLowerCase().includes(text) if(match) {results.set([...new Set([...$results, item.data])]) } else {results.set($results.filter(i=> i != item.data)) } return match } export let root let state $: state = level < visibleDepth ? Open : Closed function toggle() { state = state === Open ? Closed : Open } $: visible = text != '' ? filtered(node) : false $: text === '' ? results.set([]) : ''
https://svelte.dev/repl/407903af00114bd181f2bb314b46358d?version=3.44.1