Без секции комментариев читать некоторые статьи не так интересно. Поэтому обязательно добавим в свой блог соответствующий раздел.
Предыдущий материал: Блог на 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.
После этого в [slug] надо встроить компонент Comments и передать в него пропс с переменной title, чтобы секции с комментариями было известно название статьи: <Comments {title} />.
Все, первичная настройка выполнена. Теперь можно перейти к наполнению компонента кодом.
Настраиваем функцию загрузки комментариев
Чтобы отобразить комментарии в соответствующем блоке, нужно сначала их загрузить из базы.
-
Создаем анонимную асинхронную функцию внутри 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 создаем два параграфа, в одном из которых будет имя комментатора, а в другом – сам комментарий.
Добавляем функцию написания новых комментариев
Мало смотреть на комментарии, нам нужна возможность писать новые. Иначе как отвечать обидчикам?
Для этого мы создадим объем для комментария и будем отправлять его в массив комментариев каждый раз при нажатии на кнопку «Комментировать». Впрочем, обо всем по порядку.
-
Сначала импортируем хранилище с пользователем в 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 таким образом: 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 bind:value={comment}></textarea>
А потом добавим кнопку:
<button on:click={addComment}></button>
Готово. Можно комментить, но есть проблема – список комментариев не обновляется, когда кто-то оставляет новую запись. Надо это исправлять.
Настраиваем автоматическое обновления списка комментариев
В Supabase, как и в других базах, предлагающих возможность realtime-обновления данных, есть возможность «подписаться» на какую-либо таблицу и, улавливая изменения в ней, влиять на интерфейс или работу приложения в целом.
Создадим подписку mySubscription внутри метода onMount.
-
Создаем подписку на БД:
const mySubscription = supabase.from('Posts').on('UPDATE', payload => { comments = comments }).subscribe()
В приведенной выше записи происходит много всего. Мы тут привязываемся к событию UPDATE, то есть к обновлению данных в таблице (коим и является добавление комментария). В момент UPDATE срабатывает функция payload, а в ней у нас обновление интерфейса comments.
Теперь новые комментарии будут всегда видны пользователю, наблюдающему за статьей.
В итоге получится подобный интерфейс:
Вместо заключения
Итак, у нас есть блог с комментариями, регистрацией, картинками, тегами и кучей других полезных вещей. Мы сделали полнофункциональный блог на SvelteKit, использовав лишь одну стороннюю библиотеку и по пути перекочевав на другую базу данных (в первую очередь, из-за современных фишек, недоступных для классических БД).
Продолжение: Блог на Svelte. Часть 11: Рефакторинг
Комментарии