Создаем блог на Svelte. Часть 10: Комментарии

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

Предыдущий материал: Блог на Svelte. Часть 9: Профиль пользователя

Настраиваем базу данных

Как и всегда, начинаем с создания отдельной колонки в нашей базе данных. Нам нужно отдельное место в таблице Posts, где будут храниться комментарии к каждой статье. На этот раз создание колонки заметно отличается, потому что комментарий – это не просто кусок текста. Это имя пользователя, иногда дата создания коммента, часто картинка и прочие элементы. Это ведет нас к тому, что нам нужно хранить целый объект в качестве комментария.

Поэтому мы создаем колонку Comments в Supabase, указываем для колонки тип данных JSON и ставим галочку напротив Define as Array, также разрешаем значение NULL, чтобы в блок с комментариями мог не содержать оных.

Колонка с комментариями

Все. Теперь с этими данными можно работать, подтягивая комментарии в приложение или добавляя новые.

Создаем новый компонент и экспортируем в него нужные данные

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

Для этого создадим файл с названием Comments.svelte. Он будет полностью отвечать за отрисовку блока с комментариями.

Файл с комментариями

Этот элемент мы из корня программы сразу же импортируем на страницу с постом – [slug].svelte:

import Comments from "./Comments.svelte"

Импорт компонента с комментариями в приложение

Внутри Comments.svelte надо создать внешнюю переменную title. Будем добывать ее из [slug].svelte:

export let title

И чтобы два раза не вставать мы сразу же импортируем две нужные нам функции – supabase и onMount:

import supabase from "$lib/db"; import { onMount } from "svelte"

Эти функции понадобятся для подзагрузки данных из базы данных независимо от компонента [slug].svelte.

Импорт onMount в компонент Comments

После этого в [slug] надо встроить компонент Comments и передать в него пропс с переменной title, чтобы секции с комментариями было известно название статьи: .

Компонент Comments

Все, первичная настройка выполнена. Теперь можно перейти к наполнению компонента кодом.

Настраиваем функцию загрузки комментариев

Чтобы отобразить комментарии в соответствующем блоке, нужно сначала их загрузить из базы.

Подгрузка комментариев из базы данных

  • Создаем анонимную асинхронную функцию внутри onMount:
    onMount(async () => { })
  • Сразу же делаем запрос к БД, чтобы выудить все комментарии под нашим постом. Для этого возьмем все посты, отфильтруем по названию и выберем колонку Comments:
    let { data } = await supabase.from('Posts').select('Comments').eq('title', title)
  • Затем устраиваем проверку на наличие контента в data:
    if (data[0].Comments) { }
  • А в теле проверки прописываем переназначение переменной comments на информацию из базы данных:
    comments = data[0].Comments

Готово. Нужные данные подгружены. Теперь нужно их отрисовать. Я уже это сделал и стилизовал небольшой блок под комментарии. Сейчас разберем его основные элементы.

Интерфейс с комментариями

  • Сначала делаем общий div для всего блока.
  • Пишем название блока (в моем случае это «Комментарии»).
  • Потом создаем блок {#each}, чтобы перебрать все комментарии из переменной comments следующим образом: {#each comments as comment} {/each}
  • Внутри этого блока создаем еще один div.
  • А в еще одном div создаем два параграфа, в одном из которых будет имя комментатора, а в другом – сам комментарий.

В коде выше подразумевается, что объект с комментарием состоит из двух элементов: name и comment. Поэтому мы обращаемся к comment.name и comment.comment. В вашем случае количество значений может быть больше. Комментарии могут содержать и ссылки на изображения профиля или же дату создания коммента.

Добавляем функцию написания новых комментариев

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

Для этого мы создадим объем для комментария и будем отправлять его в массив комментариев каждый раз при нажатии на кнопку «Комментировать». Впрочем, обо всем по порядку.

Переменные для добавления новых комментариев

  • Сначала импортируем хранилище с пользователем в Comments.svelte:
    import { user } from '$lib/stores'
  • Затем добавляем переменную, где будет храниться текст комментария:
    let comment;
  • И переменную, где будет храниться имя комментатора:
    let username

Готово, теперь надо добыть часть нужной информации. Для этого придется обратиться к базе данных за никнеймом (своим же).

Выгрузка имени пользователя из базы данных

  • Пишем запрос в базу:
    let { data: userInfo } = await supabase.from('Users').select('*').eq('userId', $user.id)
  • Получив нужные данные, сохраняем их в ранее созданной переменной: username = userInfo[0].nickname

Далее создаем функцию для добавления новых комментариев в Supabase.

Код функции addComment

  • Создаем асинхронный метод addComment таким образом: const addComment = async ( ) => { }
  • Внутри него создаем объект с любым именем (у меня будет obj): const obj = { }
  • Внутри объекта указываем имя и комментарий. К ключу name прикрепляем значение username, а к ключу comment прикрепляем значение comment:
const obj = {

 "name": username,

 "comment": comment

}
  • После этого отправляем получившийся объект в массив с другими комментариями: comments.push(obj)
  • И уже новый массив выгружаем в базу данных:
    let { data } = await supabase.from('Posts').update({'Comments': comments}).eq('title', title)

Готово, теперь в Supabase попадет измененный массив комментариев.

Осталось только создать интерфейс для ввода комментария и добавить ту самую кнопку, что будет запускать функцию addComment. Для этого сделаем блок textarea со значением, привязанным к переменной comment:


А потом добавим кнопку:


Блок textarea в компоненте с комментариями

Готово. Можно комментить, но есть проблема – список комментариев не обновляется, когда кто-то оставляет новую запись. Надо это исправлять.

Настраиваем автоматическое обновления списка комментариев

В Supabase, как и в других базах, предлагающих возможность realtime-обновления данных, есть возможность «подписаться» на какую-либо таблицу и, улавливая изменения в ней, влиять на интерфейс или работу приложения в целом.

Создадим подписку mySubscription внутри метода onMount.

Подписка на изменения в базе

  • Создаем подписку на БД:
    const mySubscription = supabase.from('Posts').on('UPDATE', payload => { comments = comments }).subscribe()

В приведенной выше записи происходит много всего. Мы тут привязываемся к событию UPDATE, то есть к обновлению данных в таблице (коим и является добавление комментария). В момент UPDATE срабатывает функция payload, а в ней у нас обновление интерфейса comments.

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

В итоге получится подобный интерфейс:

Пример блока с комментариями

Вместо заключения

Итак, у нас есть блог с комментариями, регистрацией, картинками, тегами и кучей других полезных вещей. Мы сделали полнофункциональный блог на SvelteKit, использовав лишь одну стороннюю библиотеку и по пути перекочевав на другую базу данных (в первую очередь, из-за современных фишек, недоступных для классических БД).

источник

Related Posts
AllEscortAllEscort