Как создать CRUD-приложение с помощью SvelteKit


Введение

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

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

Шаги, которые мы рассмотрим:

  • Что такое Sveltekit
  • Создание приложения Sveltekit
  • Создание пользовательского интерфейса приложения
  • Чтение блогов
  • Создать новый блог
  • Обновить блог
  • Удалить блог

Что такое Sveltekit

SvelteKit — это фреймворк для создания веб-приложений любого размера, с красивым опытом разработки и гибкой маршрутизацией на основе файловой системы. Он компилирует ваши компоненты в ванильный JavaScript, который хорошо оптимизирован.

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

Он использует Vite в сочетании с плагином Svelte для обеспечения молниеносной и многофункциональной разработки с функцией Hot Module Replacement (HMR), при которой изменения в коде мгновенно отражаются в браузере.

Предварительные условия

Чтобы получить максимальную пользу от этого руководства, необходимо предварительное знание Svelte, а также убедиться, что у вас установлен Node.JS версии 16 или более поздней. Код для этого руководства доступен на Github

Создание приложения Sveltekit

Выполнив все вышеперечисленные требования, давайте создадим новое приложение Sveltekit, выполнив следующие команды.

npm create svelte@latest crud-app
Войти в полноэкранный режим Выйти из полноэкранного режима

Приведенная выше команда предложит вам выбрать конфигурации для вашего проекта. Ваш выбор должен выглядеть так, как показано на скриншоте ниже.

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

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

Приведенная выше команда установит все необходимые зависимости для запуска этого приложения.

Создание пользовательского интерфейса приложения

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

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

npm i -D @smui/button @smui/data-table @smui/dialog @smui/textfield @smui/linear-progress @smui/card
Войти в полноэкранный режим Выйти из полноэкранного режима

Приведенная выше команда установит компоненты кнопки, текстового поля и таблицы данных.

Далее добавьте Sveltematerial UI CDN в файл app.html, чтобы использовать тему по умолчанию.

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/svelte-material-ui@6.0.0/bare.min.css" />
Вход в полноэкранный режим Выйдите из полноэкранного режима

Затем создайте папку components в папке src и создайте файл Table.svelte, чтобы добавить таблицу данных для отображения постов, которые мы получим от Refine-fake-API.

// Table.svelte

<DataTable table$aria-label="User list" style="width: 100%;">
    <Head>
        <Row>
            <Cell numeric>ID</Cell>
            <Cell>Title</Cell>
            <Cell>Image</Cell>
            <Cell>Date Created</Cell>
            <Cell>Actions</Cell>
        </Row>
    </Head>
    <Body>
        {#each items as item (item.id)}
            <Row>
                <Cell numeric>{item.id}</Cell>
                <Cell>{item.title}</Cell>
                <Cell><img width="100" src={item.image?.[0]?.url} alt="" /></Cell>
                <Cell>{item.createdAt}</Cell>
                <Cell>
                    <a href={`/post/${item.id}`}>Edit</a>
                    <Button>Delete</Button>
                </Cell>
            </Row>
        {/each}
    </Body>

    <LinearProgress
        indeterminate
        bind:closed={loaded}
        aria-label="Data is being loaded..."
        slot="progress"
    />
</DataTable>

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

В приведенном выше фрагменте кода у нас есть DataTable, которая будет отображать данные из Refine-fake-API. Каждое из данных, которые мы будем отображать в ячейке таблицы, будет иметь соответствующую кнопку редактирования и удаления для изменения деталей данных.

Затем импортируйте компоненты и объявите необходимые переменные.

// Table.svelte

<script lang="ts">
    import DataTable, { Head, Body, Row, Cell } from '@smui/data-table';
    import LinearProgress from '@smui/linear-progress';
    import Button from '@smui/button';

    export let items: any[] = []
    export let loaded = false
</script>
Вход в полноэкранный режим Выход из полноэкранного режима

В приведенном выше фрагменте кода мы импортировали необходимые нам компоненты SMUI и объявили переменные items и loaded, которые будут переданы в качестве props этому компоненту.

Чтение блогов

Теперь в маршрутах +page.svelte добавьте приведенные ниже фрагменты кода, чтобы читать посты из Refine-fake-API с помощью Javascript fetch API, и чтобы они отображались в нашей таблице данных.

// +page.svelte

<script lang="ts">
  import { onMount } from 'svelte';
  import Table from "../components/Table.svelte"

  type Post = {
    createdAt: Date;
    image: any;
    content: string;
    title: string;
    id: number;
   };

    let items: Post[] = [];
    let loaded = false;

    onMount(() => loadThings(false))

    function loadThings(wait: boolean) {
            if (typeof fetch !== 'undefined') {
                loaded = false;

                fetch('https://api.fake-rest.refine.dev/posts')
                    .then((response) => response.json())
                    .then((json) =>
                        setTimeout(
                            () => {
                                items = json;
                                loaded = true;
                            },
                            // Simulate a long load time.
                            wait ? 2000 : 0
                        )
                    );
            }
    }
</script>

<Table items={items} loaded={loaded}/>
Вход в полноэкранный режим Выйти из полноэкранного режима

В приведенном выше фрагменте кода мы создали тип Post, чтобы указать Typescript объекты, к которым мы будем обращаться из данных постов.

Затем мы создали переменную items для размещения постов и создали функцию loadThings для получения данных из API и обновления переменной items. Функция loadThings будет вызываться при монтировании компонентов, которые реализованы в Svelte с помощью декоратора onMount.

Создание нового блога

С функциями чтения блога покончено, давайте добавим пользовательский интерфейс, позволяющий пользователям создавать новые записи в блоге. Для этого создайте файл Dialog.svelte в папке components и добавьте фрагмент кода, приведенный ниже.

// components/Dialog.svelte
<script lang="ts">
// @ts-nocheck
import Dialog, { Title, Content, Actions } from '@smui/dialog';
import Textfield from '@smui/textfield';
import HelperText from '@smui/textfield/helper-text';
import CharacterCounter from '@smui/textfield/character-counter';
import Card from '@smui/card';
import Button from '@smui/button';

let title = '';
let content = '';

export let open = false;

</script>
<Dialog bind:open selection aria-labelledby="list-title" aria-describedby="list-content">
    <Title id="list-title">Create New Post</Title>
    <Content id="mandatory-content">
        <Card padded>
            <Textfield variant="outlined" bind:value={title} label="Title">
                <HelperText slot="Title">Helper Text</HelperText>
            </Textfield>
            <br />
            <Textfield textarea input$maxlength={2500} bind:value={content} label="Content">
                <CharacterCounter slot="internalCounter">0 / 100</CharacterCounter>
            </Textfield>
            <br />
            <Button on:click={createPost}>Create</Button>
        </Card>
    </Content>
    <Actions>
        <Button action="accept">Close</Button>
    </Actions>
</Dialog>
Вход в полноэкранный режим Выйти из полноэкранного режима

В приведенном выше фрагменте кода мы использовали компонент Dialog для скрытия и отображения модала, Card для группировки Textfield вместе, и компонент Button для отправки данных.

В кнопке мы создали четыре переменные: open для хранения начального состояния модала, которое будет передано в качестве props из корневого маршрута, title и content для хранения значений полей ввода путем привязки к соответствующим входам.

Затем мы присоединили обработчик событий, вызывающий функцию createPost, которая будет создана позже для отправки запроса к Refine-fake-API.

Теперь добавьте приведенные ниже фрагменты кода в тег script для создания функции createPost.

// components/Dialog.svelte
async function createPost() {
    const res = await fetch(`https://api.fake-rest.refine.dev/posts`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            title,
            content,
            createdAt: Date.now()
        })
    }).then((res) => {
            res.json();
            open = false;
    });
}
Вход в полноэкранный режим Выйти из полноэкранного режима

В приведенном выше фрагменте мы отправляем POST-запрос в функцию createPost и передаем в теле запроса наши JSON-данные.

Refine-fake-API принимает больше данных, чем мы указали в полезной нагрузке, мы отправляем только те данные, которые хотим отобразить пользователю.

Наконец, добавьте приведенный ниже фрагмент кода в файл +page.svelte, чтобы добавить кнопку, которая будет показывать модальное окно.

// +page.svelte
<script>
  ...
// ====>
import Button from '@smui/button';
import Dialog from '../components/Dialog.svelte';
// <====
  ...
</script>

// ====>
<div style="display:flex; justify-content:space-between">
    <Button on:click={() => (open = true)}>Add New</Button>
</div>
<Table {items} {loaded} />

<Dialog {open} />
// <====
Войти в полноэкранный режим Выйти из полноэкранного режима

В приведенных выше фрагментах кода мы подключили обработчик событий для изменения значения переменной open для показа модала.

Обновление блога

Чтобы обновить запись в блоге, мы создадим динамический маршрут Sveltekit. Этот маршрут будет использовать id каждого блога в качестве параметра. Sveltekit реализует маршрутизацию на основе file-system-based, что означает, что маршруты вашего приложения определяются вашими директориями, и версия 3 требует, чтобы в каждой из директорий был файл +page.svelte и +page.js или +page.server.

Вы можете узнать больше о маршрутизации Sveltekit здесь. Теперь создайте папку post/[id] в routes для маршрута post. В папке [id] создайте файлы +page.svelte и +page.ts и добавьте приведенный ниже фрагмент кода в файл +page.ts.

/** @type {import('./$types').PageLoad} */
export async function load({ params }) {
    const { id } = params
    const data = await fetch(`https://api.fake-rest.refine.dev/posts/${id}`).then(res => res.json());
    return data
}
Вход в полноэкранный режим Выйти из полноэкранного режима

В приведенном выше фрагменте кода у нас есть функция load, которая будет загружать данные из API, и эта функция принимает params как объект, что дает нам доступ к объектам params для доступа к id поста в URL.

Затем мы отправляем запрос к API, чтобы получить запись блога, Id которой указан в запрашиваемом параметре. Это будет применяться ко всем постам блога, на которые мы нажмем. Функция load вернет сериализуемое значение JSON, к которому мы сможем получить доступ на странице +page.svelte через объект data.

Теперь добавьте приведенный ниже фрагмент кода на страницу +page.svelte.

// routes/post/[id]/+page.svelte
<script>
    import Button from '@smui/button';
    /** @type {import('./$types').PageData} */
    export let data;
    import Textfield from '@smui/textfield';
    import HelperText from '@smui/textfield/helper-text';
    import Card, { Content } from '@smui/card';
    import CharacterCounter from '@smui/textfield/character-counter';
    import { goto } from '$app/navigation';
    let valueA = data.title;
    let value = data.content;

    async function editPost() {
        const res = await fetch(`https://api.fake-rest.refine.dev/posts/${data.id}`, {
            method: 'PATCH',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                title: valueA,
                content: value
            })
        }).then((res) => {
            res.json();
            goto('/');
        });
    }
</script>

<div class="card-display">
    <div class="card-container">
        <Card padded>
            <Textfield variant="outlined" bind:value={valueA} label="Edit Title">
                <HelperText slot="Edit Title">Helper Text</HelperText>
            </Textfield>
            <br />
            <Textfield textarea input$maxlength={2500} bind:value label="Edit Content">
                <CharacterCounter slot="internalCounter">0 / 100</CharacterCounter>
            </Textfield>
            <br />
            <Button on:click={editPost}>Edit</Button>
        </Card>
    </div>
</div>
Вход в полноэкранный режим Выйти из полноэкранного режима

В приведенном выше фрагменте кода мы импортировали компоненты для создания пользовательского интерфейса для этой страницы с помощью компонентов Card, Textfield и Button. В каждом из этих компонентов мы отобразили данные постов в их значениях, чтобы пользователь мог редактировать только ту часть, которая ему нужна.

Затем мы создали функцию editPost, которая отправляет запрос Put к API с данными, которые мы хотим обновить в полезной нагрузке в виде JSON.

iv>

Удалить блог

Нам также необходимо дать пользователям возможность удалять посты. Мы прикрепили кнопку удаления к постам в таблице данных в файле components/Table.svelte. Поэтому добавьте приведенный ниже фрагмент кода в тег script, чтобы удалить пост из API.

// components/Table.svelte
async function deletePost(id: number) {
    const res = await fetch(`https://api.fake-rest.refine.dev/posts/${id}`, {
        method: 'DELETE'
    }).then((res) => {
        res.json();
        location.reload();
    });
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Затем обновите кнопку удаления, чтобы прикрепить функцию к событию on:click.

<Button on:click={() => deletePost(item.id)}>Delete</Button>
Войти в полноэкранный режим Выход из полноэкранного режима

Заключение

В этом руководстве мы рассмотрели, как создать CRUD-приложение с помощью Sveltekit. Мы начали с того, что узнали, что такое Sveltekit. Затем мы создали приложение для блога для демонстрации. Теперь, когда у вас есть необходимые знания, как бы вы использовали Sveltekit в своем следующем проекте? Возможно, вы сможете узнать больше о Sveltekit из документации.

Автор: Экента Клинтон

Живой пример StackBlitz

Создавайте CRUD-приложения на основе React без ограничений

Современные CRUD-приложения должны потреблять данные из множества различных источников, от пользовательских API до бэкенд-сервисов, таких как Supabase, Hasura, Airtable и Strapi.

Если вы заинтересованы в бэкенд-агностичном, безголовом фреймворке, который может подключать 15+ источников данных благодаря встроенным провайдерам и плагинам сообщества, обратите внимание на refine.

refine — это фреймворк на основе React с открытым исходным кодом для создания CRUD-приложений без ограничений.
Он может ускорить время разработки до 3 раз без ущерба для свободы стиля, кастомизации и рабочего процесса проекта.

refine является безголовым по своей конструкции и подключает 30+ бэкенд-сервисов «из коробки», включая пользовательские REST и GraphQL API.

Посетите GitHub-репозиторий refine для получения дополнительной информации, демонстраций, учебников и примеров проектов.

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