Автор оригинала: Michael Bøcker-Larsen.
Если вы работали с WordPress как Blogger или Developer раньше, вы, несомненно, знаете, что большинство сайтов построены обширными плагинами, которые выделяют шорткоды Отказ Для меня WordPress всегда казалось немного как взлом. Все сжало в Пост
Модель, главное корпус которой содержит больше типов содержимого и специальные типы данных, в зависимости от того, какие плагины Content-Plugins. Ики!
Тем не менее, именно то, как он работает, и топортное количество тем, плагинов и пользователей должно быть завет на его успех.
[галерея]
Это шорткод из документации WordPress ‘Shortcode API Отказ Шорткоды легко читать и понимать. Хотя большинство из них генерируются инструментом пользовательского интерфейса, любой может автор их автора вручную. Даже как блоггер, вам скорее всего, придется каждому сейчас.
Идея шорткодов заключается в том, что они обеспечивают супер простой контент и язык макета. Когда меня попросили помочь построить проект, который использует шорткоды в тематическом приложении Vue.js, я был вполне взволнован, чтобы увидеть, как вы можете сопоставить эти короткие казначейки на компоненты и макет Vue.js. Эта концепция может обеспечить инструмент для владельцев сайтов настроить сайт помимо того, что было достигнуто с CSS.
Приложение, которое мы строим, имеет ряд страниц. Каждый из страниц имеет несколько областей, которые могут быть настроены; Некоторые имеют более настраиваемые районы, чем другие. Например, страница проверки в веб-магазине, как правило, будет иметь менее вариантов настройки, чем передняя страница магазина, где почти все контент и макет могут быть изменены различными способами. Мы называем эти районы слоты Отказ
Общая идея состоит в том, чтобы придумать ряд базовых компонентов, которые тематический разработчик может стиль и обеспечивает базовый макет для. Структура приложений остается неизменной с точки зрения страниц, но макет и содержание в каждом из слотов могут варьироваться.
Цель: повернуть короткиекоды в составляющие Vue
Наша цель в здании этого приложения должно быть в состоянии добавить компоненты макета, так и контента для нашего Shortcode Vue.js Integration. Например:
Products
[row] [col class="s6"] [product-list name="featured" use="product-card" num=3/] [/col] [col class="s6"] [product-list name="bestsellers" use="product-card" num=3/] [/col] [/row]
В приведенном выше примере теги строки и COL (UMN) представляют компоненты макета, тогда как список продуктов и продукта-карта будет превращена в компоненты контента.
Поскольку Vue – это все о создании новых компонентов и расширение словарного запаса HTML, мы думали, что мы будем использовать наши компоненты Vue напрямую. Тем не менее, приложение, которое мы строим чрезмерно целевыми пользователями в сообществе WordPress. Поэтому мы хотели попробовать этот подход.
В основном это шаги, которые нам нужно пройти через:
- Преобразуйте строку, которую мы получаем от бэкэки в какую-то другую структуру данных, чтобы мы могли изменить макет и контент.
- Выясните, как мы можем сопоставить коды нашим компонентам, как ProductList или ProductCard.
- Выясните, как использовать Vue.js, чтобы построить новый компонент, который может создать наши компоненты.
.. а потом, наконец: демонстрация!
Шаг 1: Абстрактное синтаксическое дерево
- Преобразуйте строку, которую мы получаем от бэкэки в некоторую другую структуру данных, чтобы мы могли рассуждать о макете и содержании.
Этот первый шаг не очень интересен. Я построил небольшую библиотеку, Шорткод-токенизатор Для LEXING от блок образца выше и выпивая абстрактное синтаксическое дерево (AST).
Из приведенного выше примера мы получаем массив вложенных объектов, подобных этому:
[ { type: 'TEXT', body: "Products
" pos: 0 }, { type: 'OPEN', name: 'row', pos: 18, body: '[row]', isClosed: true, params: {}, children: [ ... a whitespace TEXT token ..., { type: 'OPEN', name: 'col', pos: 26, body: '[col class="s6"]', isClosed: true, params: { class: 's6' }, children: [ ... and so on ... ] } ] } ]
Он предоставляет нам вложенную структуру объекта, которая имеет все полученные параметры, и все элементы, помеченные в виде текста, самозакрывающегося или регулярного шума.
Мы будем использовать эту структуру данных как источник того, что построить Vue.
Шаг 2: сопоставление кодов к компонентам
- Выясните, как мы рассмотрим коды нашим компонентам, как
Производитель
илиПродукт карта
Отказ
Компоненты Vue обычно называются в зависимости от импорта родительского компонента, но Vue довольно гибкий, и вы можете ссылаться на ваши компоненты несколькими способами: Titlecase
, lowertitlecase
и Кебаб-чехол
Отказ Последнее тот же синтаксис, который мы использовали для наших коротководств, поэтому это не должно быть слишком сложно. В большинстве случаев мы можем просто использовать то же имя, чтобы обратиться к компонентам Vue:
export default { components: { ProductList } }
Производитель
Можно сейчас, как вы знаете, будем ссылаться как <Список продуктов>
В компонентном шаблоне благодаря маленькой Vue-Magic. Vue обнажает свое название функции трансформации через Vue.util
Отказ Мы будем использовать их позже.
Аргумент для создания явной карты: имя кода и имя компонента могут отличаться, потому что они следуют разным рекомендациям. Например, мы использовали [Col]
Для столбца выше, которая является сокращением для имени компонента. Я предпочитаю полные слова, так как он легче читает, но в шорткоде земля, все в порядке, чтобы пойти с короткими формой – это зеркала [ROW]
Код хорошо (вещи, которые похожи друг на друга …).
Поэтому, хотя нам на самом деле нам не нужно сопоставлять названия кода, это все равно будет хорошей идеей, потому что она не будет связываться с тем, как нам нравится работать с Vue.
Еще одно преимущество заключается в том, что мы можем ссылаться на эту карту во время анализа. Кроме того, в случае, если мы столкнулись с неизвестным кодом (от отсутствия на карте), мы можем рассматривать его как ошибку в том же месте, что и ошибки синтаксиса – вместо того, чтобы быть, чтобы ошибки возникли в Vue Runtime, при попытке создавать экземпляр компонентов. которые не существуют.
Итак, давайте создадим карту:
const codeMap = { 'col': 'column', 'row': 'row', 'product-list': 'product-list', }
ключ Является ли шорткод и ценность Является ли имя Kebab-Cound наших Vue компонентов.
Шаг 3: упаковка (или начать)
- Выясните, как использовать Vue, чтобы построить новый компонент, который может создать наши компоненты.
Теперь, когда у нас есть AST, нам нужно разбирать или рендерировать шаблоны и компоненты, используя карту, которую мы определены на предыдущем шаге.
Vue предоставляет несколько встроенных компонентов, которые могут сделать ваши страницы более динамичными в том смысле, что вам не нужно указывать, какие компоненты отображаются или о том, как они отображаются заранее. Это <Компонент>
и <Слот>
соответственно.
<Компонент>
Функциональность компонента близка к тому, что мы хотим. Тем не менее, мы должны включить все наши компоненты на каждой странице и в каждом родительском компонентах, где мы хотим использовать или шорт-код, поскольку слот, в теории, могут содержать ссылки на все наши компоненты.
Это немного громоздки, чтобы сказать наименее. Мы не хотим повторять это для каждого родительского компонента. Эта рута также должна быть инкапсулирована.
Требования
Итак, давайте упасть это. Мы сделаем новый компонент, который похож на <Компонент>
Но тот, который имеет знание всех компонентов, которые мы хотим разоблачить в слот шорт. Мы назовем это <Код-слот>
Отказ
Но во-первых, вспомните наш шаблон представляет собой смесь текста (HTML) и короткокодов. По сути, мы можем иметь текст вокруг и между каждым из открытых и закрытых кодов. Нам нужно добавить это на шаблон.
Когда у вас есть очень динамичный контент, <Компонент>
и <Слот>
может быть недостаточно. В этом случае вы можете написать свою собственную функцию рендера.
(Внутренне, все ваши шаблоны превращаются в функции рендеринга.)
Наш компонент действует как контроллер с точки зрения того, что оказывается, но не добавляет какое-либо содержание значения или функциональность, помимо содержания слота. Для таких сценариев вы бы пошли на Функциональный компонент , потому что у него меньше над головой, поскольку он не поддерживает состояние. Вы просто пропустили контроль на другой компонент. Однако, поскольку мы также должны сделать текст, у нас нет одного компонента, который может справиться со всеми нашими потребностями. По этой причине мы будем использовать обычный компонент.
(Если кто-то знает, если и как можно сделать следующее в качестве функционального компонента, я хотел бы узнать, как!)
Поехали. Нам понадобится Vue и Tokenizer:
// components/CodeSlot.vue import { default as Tokenizer } from 'shortcode-tokenizer' import Vue from 'vue'
Мы также хотим импортировать все компоненты, которые мы хотим включить в качестве шорткодов:
import Row from 'components/Row' import Column from 'components/Column' import ProductList from 'components/ProductList' import ProductCard from 'components/ProductCard'
Затем мы добавляем нашу карту, но с небольшим поворотом. Нам нужна карта в двух случаях.
- Чтобы получить имя Kebab-Cound для создания шаблона
- пройти в
Компоненты:
Свойство нашего компонента, поэтому вместо сопоставления из кода до имени компонента мы рассмотрим непосредственно в импортируемый компонент:
const codeMap = { 'row': Row, 'column': Column, 'col': Column, 'product-list': ProductList, 'product-card': ProductCard } const allComponents = Object.values(codeMap) .reduce((all, c) => { all[Vue.util.hyphenate(c.name)] = c return all }, {})
Обратите внимание, что у нас обоих Col
и Колонка
в Кодемап
– Это означает, что оба могут быть использованы в качестве шорткодов. Тем не менее, Vue будет жаловаться, если вы попытаетесь использовать Col
Потому что это уже тег HTML. Вместо того, чтобы использовать карту кода напрямую, мы рассмотрим его новым объектом, в котором ключ основан на выделенном (кебаб) версии имени компонента.
(Примечание. Если вы используете WEBPACK или что-то подобное, вам нужно добавить a Имя:
Свойство на ваши компоненты. В противном случае имя будет нечетное внутреннее значение WebPack.)
Компонент
Итак, давайте начнем плоть фактический компонент:
export default { props: { content: { type: String, required: true }, strict: { type: Boolean, default: true } }, methods: { renderContent() { // Turn AST into template and handle syntax error } }, created: { this.tokenizer = new Tokenizer() }, render(h) { return h(Vue.component('code-wrapper', { template: this.renderContent(), components: allComponents })) } }
Идея такого подхода является программно создать еще один компонент – <Кодовая обертка>
– как ребенок нашего <Код-слот>
составная часть. В нашем шаблонном коде из родительского компонента мы включаем слот кода:
Так сказать, что мы поместим список продуктов в слоте боковой панели:
Featured
[product-list name="featured" num=3 use="product-card"/]
Тогда наша Vue иерархия в конечном итоге выглядит так:
(CodeSlot – наш контрольный компонент, который создает Codewrapper, который является шаблоном, который содержит как HTML, так и наш пользовательский компонентный продукт)
Рендеринг
Я не буду покрывать весь процесс рендеринга, но вы можете посмотреть его больше в этот гид который включает в себя компонент в полном объеме.
Тело этой функции может быть довольно просто. Важной частью является то, как мы обрабатываем синтаксические ошибки, чтобы предотвратить заблуждение нашего Vue приложения.
export default { ... methods: { renderContent() { try { let ast = this.tokenizer .input(this.content) .ast() let content = ast .map(renderToken) .join('') return ensureOneRoot(ast, content) } catch (err) { console.error(err) return `${err.message}` } } } ... }
Наше значение SPOP CONPORT (из нашего родителя) передается в токенизатор, который возвращает AST, массив жетонов корня. Мы передаем каждый токен в функцию визуализации (не отображается здесь), что возвращает часть нашего окончательного шаблона, который мы затем соединяем со всеми другими частями. Наконец, прежде чем вернуться, мы гарантируем, что сгенерированный шаблон имеет только один корню – требование Vue компонентов.
В процессе рендеринга я просто пропускаю токены через серию функций трансформатора рекурсивно. В качестве примера это функция рендеринга для кодов, которые имеют открытую и близкую часть:
function renderOpen(token) { if (token.type === Tokenizer.OPEN) { let name = getComponentName(token) let params = renderParams(token) let children = token.children .map(renderToken) .join('') token.output = `<${name}${params}>${children}` } return token }
Вам не нужно зеркально использовать AST. Вы можете пропустить узлы, добавлять новые, или как в этом примере, держать живой
Параметр преобразуется в обертку компонента:
// example input: [product-list keep-alive/] function wrapKeepAlive(token) { if (typeof token.params['keep-alive'] !== 'undefined') { token.output = `${token.output} ` } return token }
Обработка ошибок
Вы должны естественным образом подтвердить ваши коды во всех авторовных контентах перед публикацией, но мы будем справиться с этим здесь, тем не менее. Кроме того, этот компонент также можно использовать в CMS, а также Шорткод-токенизатор Может использоваться на бэкэне, если вы запустите Node.js.
Для этой демонстрации обрабатывание не более чем выводит ошибку с токеном и выводом его на консоль.
Демонстрация
Наш следующий шаг будет выяснить, насколько хорошо это работает с тематикой. На данный момент давайте посмотрим, что мы достигли.
Вопросы и обратная связь приветствуются. Я все еще относительно новичок в Vue.js сам. Если вы только что начали изучать Vue.js, обязательно проверить начать работу с Vue.js: зачем его использовать?
(Обратите внимание, насколько ошибки синтаксиса отображаются всякий раз, когда коды являются неполными. ProductCard
и ProductListiteM
являются двумя разными компонентами, которые могут использовать компонент Productlist
rooms и
Колонка - это простые обертки вокруг CSS Grid Framework.)
Рекомендации: