Учебник по созданию структуры статьи, реагирующей на вашу прокрутку, с помощью react-scrollspy
Посещали ли вы некоторые сайты с документацией и учебными пособиями, которые позволяют вам видеть, какой раздел вы читаете сбоку? Если вы хотите улучшить читабельность своего веб-сайта Gatsby. В этой статье я поделюсь своим процессом создания интерактивного компонента таблицы содержимого, который может реагировать на вашу прокрутку.
Давайте посмотрим на требование: 1. Читатель сможет легко перемещаться по разделам контента 2. Читатель сможет узнать свой прогресс чтения
Мы будем использовать пакет с именем react-scrollspy
, чтобы определить, находятся ли заголовки в области просмотра, что в ответ вызовет активное имя класса.
Включив компонент «Таблица содержания», пользователи смогут легко перемещаться по вашей статье, находя интересующий их контент. Давайте начнем и перейдем к шагу 2, если у вас уже есть сайт Gatsby.
1. Создайте сайт Гэтсби
Сначала мы установим простой стартер MDX.
gatsby new gatsby-tutorial-table-of-content https://github.com/hagnerd/gatsby-starter-blog-mdx
Используйте yarn
или npm install
для инициализации репозитория.
2. Установите react-scrollspy и gatsby-remark-autolink-headers.
Взглянув на react-scrollspy
, нам нужно будет предоставить заголовки для каждой страницы компоненту, который, к счастью, генерируется автоматически по умолчанию в каждом почтовом узле. Нам также нужно будет указать имя класса для активации, когда он находится в поле зрения.
yarn add react-scrollspy gatsby-remark-autolink-headers
В gatsby-config.js
вам нужно будет добавить gatsby-remark-autolink-headers
в gatsbyRemarkPlugins
.
3. Обновить пост-запрос GraphQL
Включите tableOfContents
в запрос GraphQL шаблона сообщения в блоге, в моем случае это blog-post.js
в папке шаблонов. После этого, если вы используете GraphiQL, вы сможете увидеть оглавление в виде объекта. Мы вызовем все значения url
в объекте и вернемся в виде массива.
4. Передача Post Props в Toc компонент
Создайте новый файл с именем Toc.js
в папке Components. Мы будем добавлять функции шаг за шагом, чтобы изолировать проблемы, которые могут возникнуть. Добавляя очень простой компонент, мы должны убедиться, что все реквизиты будут переданы в первую очередь.
import React from ‘react’
export default function Toc(props) { const { post } = props console.log(post) return <h3>Table of Content</h3> }
Сохраните файл и вернитесь к blog-post.js
и импортируйте компонент Toc.
import Toc from '../components/toc'
Затем я добавлю Toc непосредственно перед MDXRenderer.
<Toc post={post.tableOfContents} /> <MDXRenderer>{post.body}</MDXRenderer>
На данный момент будет отображаться только заголовок Table of Contents h3. Но в консоли, когда мы зарегистрировали post props. Мы также можем проверить, возвращаются ли объекты tableOfContents
.
5. Сопоставление таблицы реквизитов контента
Для более простой демонстрации мы будем перечислять только все заголовки первого уровня в таблице содержания. Давайте обновим toc.js
, сопоставив значение реквизита. Таким образом, мы сможем получить доступ ко всей информации о заголовках и ссылкам из tableofContents
из GraphQL.
return ( <nav> {post.items.map(p => ( <li key={p.url}> <a href={p.url}>{p.title}</a> </li> ))} </nav> )
Поскольку мы установили gatsby-remark-autolink-headers
для автоматического добавления якоря для каждого заголовка. Щелчок по оглавлению немедленно перенаправит к заголовку.
6. Стилизация компонента «Таблица содержимого» сбоку
Теперь, когда основная функциональность завершена, давайте позаботимся о стиле, сначала покажем, что мы можем проще протестировать прокрутку. Здесь я буду использовать простейшую реализацию с использованием CSS. Но любая реализация стиля должна работать нормально.
Давайте создадим Toc.css
в той же папке и импортируем его в компонент.
import './Toc.css'
Мы зафиксируем оглавление в правой части окна, чтобы пользователи могли легко перемещаться независимо от того, в какой части страницы они находятся. Кроме того, поскольку мы не хотим изменять обычный стиль списка. Мы укажем имя класса .toc-list
, которое будет добавлено на следующем шаге.
Мы также добавим класс is-current
, чтобы Scrollspy мог добавить имя класса, когда заголовок находится в поле зрения.
nav { position: fixed; top: 50vh; right: 5vw; margin-left: 36px; max-width: 250px; } ul.toc-list { border-left: 1px solid #363636; } ul.toc-list > li { list-style-type: none; margin-left: 24px; font-size: 13px; } ul.toc-list > li > a { color: #c2c2c2; text-decoration: none; border-bottom: 0; transition: 1s all ease-in-out; } ul.toc-list > li.is-current > a { color: black; }
7. Внедрите React Scrollspy
И последнее, но не менее важное: нам нужно будет определить, находится ли заголовок в поле зрения. react-scrollspy
поможет нам определить, находится ли якорь в поле зрения после того, как мы пройдем через 2 объекта.
- Список якорных URL-ссылок в виде массива
- Имя класса, когда виден заголовок
На расследование ушло некоторое время, но поскольку Гэтсби уже tableofContents
удобно добавил якорь, нам действительно нужно удалить #
из предоставленного объекта. Вот простая функция для вызова значения url
в объекте и удаления первого символа.
let url = post.items.map(function(post) { return post['url'].substring(1) })
После этого давайте импортируем Scrollspy сразу после nav
и передаем url
и добавляем текущее имя класса:
<Scrollspy items={url} currentClassName="is-current" className="toc-list"> {post.items.map(p => ( <li key={p.url}> <a href={p.url}>{p.title}</a> </li> ))} </Scrollspy>
Окончательный файл для Toc.js
должен выглядеть так
import React from 'react' import Scrollspy from 'react-scrollspy' import './Toc.css' export default function Toc(props) { const { post } = props let url = post.items.map(function(post) { return post['url'].substring(1) }) return ( <nav> <Scrollspy items={url} currentClassName="is-current" className="toc-list"> {post.items.map(p => ( <li key={p.url}> <a href={p.url}>{p.title}</a> </li> ))} </Scrollspy> </nav> ) }
Вот и все. Я создал минимальное репо, используя Gatsby Starter Blog MDX. Не стесняйтесь ссылаться на него и поднимать любые вопросы на Github. Вы также можете просмотреть демо здесь.
Вот некоторые из ошибок и вопросов, с которыми я столкнулся при разработке компонента Table of Contents с помощью Gatsby.
Как сделать условный рендеринг, когда вообще нет заголовков?
В настоящее время, если у вас есть сообщение в блоге без заголовка. Вы столкнетесь с ошибкой. Нам нужно будет добавить условный рендеринг в оглавление только тогда, когда он будет доступен в шаблоне поста.
/*blog-post.js*/ {!!post.tableOfContents.items && <Toc post={post.tableOfContents} />}
Как отладить все ошибки с помощью Gatsby Build?
Если у вас много постов в блоге, вы не сможете протестировать всех самостоятельно. Если вы использовали gatsby develop
для тестирования компонента Table of Contents. Я настоятельно рекомендую вам использовать gatsby build
для проверки всех сообщений в блоге перед фиксацией. Убедитесь, что в сообщении блога нет ошибок. Мне удалось найти запись в блоге без каких-либо заголовков и одну запись в блоге с неправильной иерархией заголовков (h3 перед h2), что привело к ошибке сборки.
Плагин в gatsby-remark-autolink-headers
добавляет значок перед каждым заголовком, который он обрабатывает. Согласно документации, make icon: false
в параметрах плагина удалит значки перед якорными заголовками.
/*gatsby-config.js*/ { resolve: `gatsby-remark-autolink-headers`, options: { icon: false, }, },
Как сделать прокрутку плавной?
Установите smooth-scroll
, добавьте следующий код в Layout.js
или в любое другое место, которое будет загружаться на каждой странице.
if (typeof window !== 'undefined') { // eslint-disable-next-line global-require require('smooth-scroll')('a[href*="#"]') }
Что дальше?
Есть еще некоторые проблемы с существующими решениями. Например, react-scrollspy
распознает только заголовок, а не заголовок + следующие абзацы. Столь длинная статья может столкнуться с такой проблемой (Заголовок 1 в поле зрения -> Вне поля зрения -> Заголовок 2 в поле зрения).
Кроме того, в настоящее время отображается только заголовок первого уровня. Добавление цикла также станет следующим шагом в улучшении оглавления.
И последнее, но не менее важное: стоит поработать над отображением на мобильных устройствах, в настоящее время оглавление не будет отображаться на мобильных устройствах, поскольку большинство моих читателей приходят с настольных компьютеров. Но реализация плавающей кнопки с всплывающим меню также была бы возможным решением.
Первоначально опубликовано на https://desktopofsamuel.com.