Правильно ли я разделяю ввод диапазона на отдельный компонент Svelte? Есть ли способ лучше?

Я новичок в Svelte и мне это нравится! Создание однокомпонентного приложения с несколькими частями пользовательского интерфейса и общего состояния до смешного весело и легко (для этого нужно иметь промежуточные знания HTML, CSS и JS, а также знания React для начинающих).

Однако в конечном итоге я надеюсь создать более сложные приложения, которые будут включать в себя множество входных данных и состояний, поэтому, очевидно, мне нужно понимать, как использовать состояние между компонентами.

Однако я немного запутался в том, как лучше всего создать настраиваемый компонент ввода и лучше всего использовать состояние в другом месте. В частности, я хочу создать компонент input type="range" с индивидуальным стилем и использовать его в родительском элементе.

В ходе написания этого вопроса я нашел подход, который, кажется, работает, но я не могу найти что-то в документации или в Google, что полностью соответствует этому случаю, поэтому я не уверен в своем решении. Вот что я придумал: https://github.com/arrowtype/svelte-slider/ < / а>.

Краткое изложение моего решения

Я начал с шаблона SvelteJS (https://github.com/sveltejs/template).

Моя App.svelte такая:

<script>
    import SimpleSlider from './SimpleSlider.svelte'

    export let sliderValA = 0;
    export let sliderValB = 15;
</script>

<main>
    <h1>A simple SvelteJS slider component</h1>

    <p>Slider A value is {sliderValA}</p>
    <SimpleSlider bind:value={sliderValA} min="0" max="10" step="1"/>

    <p>Slider B value is {sliderValB}</p>
    <SimpleSlider bind:value={sliderValB} min="0" max="30" step="5"/>

    <p>A + B is {sliderValA + sliderValB}</p>
</main>

А SimpleSlider.svelte выглядит так:

<script>
    export let value = 5;
    export let min = 0;
    export let max = 10;
    export let step = 1;
</script>

<div class="slider-container">
    <input type="range" bind:value={value} min={min} max={max} step={step}>
    <span>{value}</span>
</div>

<style>
    .slider-container {
        display: flex;
        align-items: center;
    }
    input {
        margin:0 0.5em 0 0;
    }
</style>

В моем тестировании это похоже на работу. Но мне было сложно туда добраться, и я не уверен, что это лучший способ.

Должен ли я делать что-то еще, например, использовать модуль svelte/store для обработки глобального состояния (если нет, когда мне это может понадобиться)?


person thundernixon    schedule 30.05.2020    source источник


Ответы (1)


Честно говоря, это выглядит действительно хорошо и кажется мне подходящим вариантом. Зачем вам нужен глобальный магазин? Его использование означает, что данные будут везде доступны и сохранены в вашем приложении, что звучит излишне, когда компонент нужен только в одной маленькой форме. Так лучше поступать с небольшими независимыми компонентами.

Я могу придумать только небольшие улучшения для вашего SimpleSlider.svelte:

<script>
  export let moreProps = {}
</script>

<div class="slider-container">
    <input type="range" bind:value {min} {max} {step} {...moreProps}>
    <span>{value}</span>
</div>

Этот подход использует преимущества сокращенного синтаксиса и сокращает объем кода. moreProps будет, если вы решите передать дополнительные свойства, например disable:

<SimpleSlider bind:value={sliderValA} min="0" max="10" step="1" moreProps={{disabled:true}}/>
person Gh05d    schedule 30.05.2020
comment
Отлично, спасибо, что указали на эти дополнительные улучшения! - person thundernixon; 30.05.2020
comment
Это так невероятно, что Svelte предлагает эту стенографию и способ автоматического распространения в других реквизитах. ???? Думаю, я также могу позволить step войти в moreProps, так как по умолчанию шаг для ввода диапазона равен 1, насколько мне известно. - person thundernixon; 30.05.2020
comment
О, обновление: применяя это на практике, я понимаю, что moreProps - не такая уж необычная функция Svelte, как я изначально думал; это переменная, которую вы создаете, а затем Svelte просто позволяет распространять свойства из этой переменной. Отлично! - person thundernixon; 30.05.2020
comment
Извините, еще одно обновление: в немного более сложном примере я пытаюсь прослушивать события слайдера и запускать различные обработчики на основе этого (например, преобразование значений для автоматической настройки связанных слайдеров). Для этого мне нужно включить переадресацию событий в компонент Slider: <input id="slider" type="range" bind:value {min} {max} {...moreProps} on:change on:input> - person thundernixon; 30.05.2020
comment
Да, функция распространения - это новый синтаксис Javascript = es6, и это очень удобно, когда вы хотите передать неизвестное количество свойств компоненту. Хорошо то, что базовый компонент игнорирует любые неизвестные ему свойства и не выдает ошибку. Что делает on:input в вашем случае? Разве он не должен быть таким же, как обработчик on:change, поскольку вы не можете вводить текст в этот конкретный компонент? - person Gh05d; 31.05.2020