Простой, многоразовый Svelte Modal


Intro

Я заметил этот пост о создании React Modal, поэтому я решил опубликовать свой вариант Svelte Modal, но с большим количеством функций и возможностью многократного использования.

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

Вы также сможете закрыть модальное окно, щелкнув мышью вне модального окна, нажав клавишу Escape или нажав кнопку OK.

Это небольшая вариация компонента, который я создал для своего участия в хакатоне redis, где он использовался для отображения сообщений об ошибках.

Шаг за шагом

Начните с открытия терминала/консоли

Перейдите в директорию, в которой вы хотите разместить проект

Запустите

npm create vite@latest
Войдите в полноэкранный режим Выйдите из полноэкранного режима

Введите имя проекта, в моем случае svelte-modal
Выберите svelte в качестве фреймворка
Выберите обычный svelte

Как сказано в инструкции, перейдите в каталог и запустите

npm install
Войти в полноэкранный режим Выйти из полноэкранного режима

Я ленив и не люблю писать много CSS, поэтому для этого я буду использовать picocss.
Итак, запустите

npm install @picocss/pico
Войти в полноэкранный режим Выйти из полноэкранного режима

Запустите сервер разработчиков с

npm run dev
Войти в полноэкранный режим Выйдите из полноэкранного режима

Теперь вы должны увидеть это в браузере.

Давайте приступим к коду!
Перейдите к файлу App.svelte в папке src. Он содержит шаблон для страницы, которую вы только что открыли в браузере.
Давайте удалим его и заменим на:

<script>
</script>

<main>
    <button>Show modal</button>
</main>
Войти в полноэкранный режим Выйти из полноэкранного режима

Перейдем к app.css и просто удалим все содержимое, так как оно не нужно.

Теперь импортируем pico.css
перейдем в main.js и добавим следующее

import '@picocss/pico/css/pico.min.css';
Вход в полноэкранный режим Выйти из полноэкранного режима

в верхней части файла.
Теперь это должно выглядеть следующим образом:

import '@picocss/pico/css/pico.min.css';
import './app.css';
import App from './App.svelte';

const app = new App({
    target: document.getElementById('app'),
});

export default app;
Вход в полноэкранный режим Выйти из полноэкранного режима

Этот модал будет использовать хранилище Svelte. В этом магазине будет храниться сообщение модала, заголовок и состояние открытия/закрытия. Использование магазина означает, что мы сможем запускать показ модала как из компонентов Svelte, так и из обычного кода Javascript.

Давайте создадим новую папку stores внутри папки src/lib. Создайте новый файл в папке stores с именем index.js.

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

import { writable } from 'svelte/store';
export const modal = writable({ open: false, title: 'Default title', message: 'Default message' });
Вход в полноэкранный режим Выйдите из полноэкранного режима

Теперь магазин готов к использованию.
Давайте создадим собственно модальный компонент. Обычно я создаю папку components, но для этого примера мы просто поместим файл в папку ‘src/lib’.

Создадим файл с именем Modal.svelte.

В этот файл мы поместим приведенный ниже код, я объясню, что он делает немного позже.

<script>
    import { modal } from '../lib/stores/';
    const close = () => ($modal.open = false);

    const handle_keydown = (e) => {
        if (e.key === 'Escape') return close();
    };
</script>

<svelte:window on:keydown|once={handle_keydown} />

<dialog open on:click|self|preventDefault={close}>
    <article>
        <h3>{$modal.title}</h3>
        <p>
            {$modal.message}
        </p>
        <footer>
            <button on:click|once={close}>OK</button>
        </footer>
    </article>
</dialog>

Вход в полноэкранный режим Выйти из полноэкранного режима

Давайте вернемся к файлу App.svelte и подключим его, чтобы можно было все опробовать.

<script>
    import Modal from './lib/Modal.svelte';
    import { modal } from './lib/stores/';
</script>

<main>
    {#if $modal.open == true}
        <Modal />
    {/if}
    <button on:click={() => ($modal.open = true)}>Show modal</button>
</main>

Вход в полноэкранный режим Выход из полноэкранного режима

Теперь у нас есть вот это:


И если нажать на кнопку:

Итак, мы импортируем компонент Modal и модальный магазин.
Мы помещаем компонент Modal внутрь Svelte-if. $modal ссылается на магазин, поэтому мы показываем компонент, только если $modal.open — true.

Теперь у нас есть модальное окно, которое будет закрыто, если щелкнуть мышью за пределами модального окна, нажать кнопку escape на клавиатуре или нажать кнопку ok модального окна. Его можно отобразить из любого места, просто импортировав магазин и установив open в true, и таким же образом можно установить заголовок и сообщение для отображения различных вещей, например, сообщений об ошибках.

Теперь давайте углубимся в код, который заставляет это работать. Учитывая функциональность, которую он обеспечивает, код удивительно мал.

Вот компонент Modal.svelte.

<script>
    import { modal } from '../lib/stores/';
    const close = () => ($modal.open = false);

    const handle_keydown = (e) => {
        if (e.key === 'Escape') return close();
    };
</script>

<svelte:window on:keydown|once={handle_keydown} />

<dialog open on:click|self|preventDefault|once={close}>
    <article>
        <h3>{$modal.title}</h3>
        <p>
            {$modal.message}
        </p>
        <footer>
            <button on:click|once={close}>OK</button>
        </footer>
    </article>
</dialog>
Вход в полноэкранный режим Выйти из полноэкранного режима

Импортируйте магазин, чтобы его можно было использовать.

import { modal } from '../lib/stores/';
Вход в полноэкранный режим Выход из полноэкранного режима

Функция, которая закроет модальное окно, установив магазин.

const close = () => ($modal.open = false);
Войти в полноэкранный режим Выход из полноэкранного режима

Обработчик для keydown, который будет показан немного ниже, вызывая функцию close() только при нажатии escape.

const handle_keydown = (e) => {
        if (e.key === 'Escape') return close();
    };
Вход в полноэкранный режим Выход из полноэкранного режима

В Svelte мы можем использовать специальный тег svelte:window. Здесь мы используем его для привязки обработчика событий для нажатия клавиши к объекту окна, как это можно сделать в обычном javascript.
Он использует специальный модификатор DOM once. Благодаря использованию once слушатель удаляет себя после выполнения одного раза, что может быть полезно во многих ситуациях

<svelte:window on:keydown|once={handle_keydown} />
Вход в полноэкранный режим Выйти из полноэкранного режима

В pico.css модалы легко создаются с помощью элемента с элементом внутри. Это не специальные элементы, а обычные html-элементы.

Но давайте проанализируем приведенный ниже код. Существует on:click слушатель, привязанный к элементу <dialog>, поэтому полупрозрачная область вне модального поля. И запускает функцию close(), заставляя диалог закрыться.

<dialog open on:click|self|preventDefault|once={close}>
Вход в полноэкранный режим Выход из полноэкранного режима

При использовании self функция on:click сработает только в том случае, если мы явно щелкнем в любом месте элемента <dialog>, то есть на фоне. Без этого on:click также сработает, если щелкнуть в любом месте модального окна. Удобная функция 🙂

preventDefault не должен быть нужен, но я поместил его сюда, потому что хотел показать его. Она предотвращает поведение по умолчанию и является тем же самым, что и использование preventDefault() в обработчике событий. Это может быть удобно, если вы, например, хотите определить встроенную функцию для обработчика on:click, например:

on:submit|preventDefault={(e)=>do something simple}
Войти в полноэкранный режим Выйти из полноэкранного режима

Svelte полон таких умных вещей, как эта, проверьте документацию, если вам интересно узнать о других модификаторах DOM.

Надеюсь, вы чему-то научились. Это было утомительно писать, я буду писать devlogs. 😉

Оцените статью
devanswers.ru
Добавить комментарий