Как и зачем использовать JSX с Vue.js
Я знаю, что есть, по крайней мере, некоторые поклонники Vue.js, которые ненавидят идею размещения HTML в JavaScript. Файлы .vue
, которые помещают JavaScript в <script>
теги «там, где он принадлежит», являются наиболее близкими к объединению разметки и кода шаблона. Эта статья также для них. Я постараюсь объяснить, почему их опасения не достигают цели. Затем я объясню, как начать работу с JSX и TypeScript на Vue.js.
Нет, не совсем, это не HTML. Это другой синтаксис для того же вызова
h()
.
Что на самом деле представляет собой JSX
Если вы уже знаете, что такое JSX, не стесняйтесь переходить к следующему разделу, где я расскажу о том, как выполняется настройка.
JSX - это не HTML. Период. Попытка сравнить JSX с HTML похожа на попытку сравнить JavaScript с Java. Они могут выглядеть похожими, но это совершенно разные звери.
Чтобы понять JSX, вам сначала нужно понять функцию рендеринга Vue.js.
Как вы уже знаете, Vue.js может использовать скомпилированные шаблоны или функции рендеринга. Скомпилированные шаблоны легко рассуждать (если вы знаете HTML). Это то, чем они являются: разметка HTML в строковой форме. Они компилируются в JavaScript. Функции рендеринга, как следует из названия, уже содержат код, поэтому компиляции нет (во время выполнения или иначе). Они генерируют виртуальные деревья DOM.
Обычно вы пишете такие функции рендеринга:
@Component class Foo extends Vue { name = "foo"; public render(h: CreateElement): VNode { return h( "div", { "class": "foo", attribs: {"data-id": "12"} }, [this.name] ); } }
Это преобразуется в <div class="foo" data-id="12">foo</div>
. Печатать это не так сложно, но нужно подумать, прежде чем вы поймете, что делает. Я сам смог написать это после 15 минут практики. Я не думаю, что это такой уж плохой способ его написания, но он не похож на HTML, и я понимаю, что кому-то может казаться, что это могло произойти из-за чьих-то посторонних взглядов.
Этот API низкоуровневый. Он предназначен для того, чтобы оставаться под сахарным покровом скомпилированных шаблонов и не использоваться напрямую (по крайней мере, это мое предположение; я не могу представить, зачем кому-то делать этот API для повседневного использования. -дневное использование).
Просто щелкни пальцем. Уродливый код, приведенный выше, превращается примерно в это:
@Component class Foo extends Vue { name = "foo"; public render(h: CreateElement): VNode { return ( <div class="foo" attribs={{"data-id": "12"}}> {this.name} </div> ); } }
Это что-то вроде HTML, правда? Если прищуриться очень сильно. И посмотри в другую сторону. Нет, не совсем, это не HTML. Это другой синтаксис для того же вызова h()
. Не больше и не меньше: строго синтаксис. Под капотом вы все еще вызываете функции, и вы должны знать сигнатуру функции, чтобы успешно ее вызвать. Вы не можете, например, сделать что-то вроде <div class="foo" data-id="12">
. Это не будет работать.
В качестве примечания: у React гораздо более приятный синтаксис для написания JSX (они его изобрели, так что он фигурирует).
Однако если вы сможете осознать это, вы поймете, что у него есть несколько важных преимуществ. В отличие от языка шаблонов, который по сути представляет собой DSL для создания шаблонов, у вас есть все возможности JavaScript.
Как заставить JSX работать с TypeScript
Теперь, когда мы ясно понимаем, что JSX находится в контексте Vue.js, давайте поговорим о том, как заставить его работать с TypeScript.
Как правило, это довольно просто, но вам нужно остерегаться некоторых вещей, которые было довольно сложно найти.
Шаг 1. Настройте компилятор TypeScript
Файл tsconfig.json
должен содержать следующие параметры компилятора:
{ "compilerOptions": { .... "jsx": "react", "jsxFactory": "h" } }
Параметр jsx
включает JSX. Второй вариант, jsxFactory
, указывает TypeScript использовать h()
вызовы для тегов JSX. По умолчанию это React.createElement()
, что, как вы, наверное, догадались, работает только с React.
Шаг 2. Добавьте определения типа JSX
Где-то в вашем проекте вам нужно включить это определение типа:
import Vue, { VNode } from "vue"; declare global { namespace JSX { interface Element extends VNode {} interface ElementClass extends Vue {} interface IntrinsicElements { [elem: string]: any; } } }
Я добавляю это в свой проект: обычно у меня есть файл с именем app.d.ts
в корне исходных текстов проекта, и я добавляю туда такую строку:
///<reference path="./types/jsx.d.ts"/>
В качестве альтернативы вы можете добавить typesRoot
ключ в свой tsconfig.json
и указать в нем каталог, в котором вы будете хранить файл jsx.d.ts
:
{ "compilerOptions": { ... "typesRoot": ["./node_modules/@types", "./types"] } }
Шаг 3: переименуйте модуль TypeScript в .tsx
Модули, содержащие JSX, должны иметь .tsx
расширение. Не спрашивайте почему.
Шаг 4. Прочтите об API
API - это непросто. На самом деле это довольно некрасиво. Но вы должны знать это, чтобы писать на JSX эффективно.
Как сделать это лучше
Это мысль, с которой я сейчас обдумываю. Весь опыт можно было бы значительно улучшить, если бы h()
API был немного лучше с самого начала.
Например, если бы он мог разумно различать атрибуты HTML, свойства, привязки, стили и классы, нам бы не пришлось их вкладывать. И так далее. Поскольку h()
- это просто функция в локальной области видимости, я полагаю, мы могли бы подойти к ней довольно творчески.
Это просто домашнее задание или любимый проект.
Заключение
Надеюсь, теперь вы хотя бы понимаете, что такое JSX и хотите ли вы его использовать. Если вам понравилась эта идея, я надеюсь, что помог вам понять, как интегрировать ее в TypeScript.
Если вы нашли эту статью полезной, не забудьте порекомендовать ее и поделиться ею.