Главная » Статьи » Использование JSX с Vue и зачем это нужно

Использование JSX с Vue и зачем это нужно

Использование JSX с Vue и зачем это нужно

От автора: сегодня мы поговорим о совместном использовании Vue JSX. Vue.js обладает легким API и парой опций определения HTML шаблонов в компонентах. Можно использовать вариант с тегом template, определить свойство template в корневом компоненте или использовать компоненты Single-File.

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

Так зачем же использовать JSX вместо других определений шаблонов?

JSX легко читать. <div>…</div> объективно лучше чем this.$createElement(‘div’, {}, […])

Серьезно, это просто JS

Vue поддерживает JSX

JSX облегчает импорт и управление Vue компонентами

Быстрое введение

Давайте я вам на примере поясню, почему JSX – это хорошо.

Нам нужно создать компонент <TextField/>, который одновременно может быть input для однострокового текста и textarea для многострокового текста. Наш шаблон может быть таким:

<div> <textarea v-if="multiline" v-model="content" :name="name" :placeholder="placeholder" :aria-invalid="false"> <input v-else v-model="content" :name="name" :placeholder="placeholder" :aria-invalid="false"> </div>

Как видно из кода сверху, мы сразу сталкиваемся с парой проблем типа дублирования кода и т.д. Представьте, как вам придется поддерживать свойства на input. Этот маленький кусок кода вырастет, и его обслуживание превратится в кошмар.

Чтобы это исправить, нам нужно пойти по низкому уровню с Vue. Чтобы исправить этот беспорядок, нам нужно ближе подобраться в внутреннему API Vue.

Метод render()

У каждого компонента в Vue есть метод render. Здесь Vue выбирает компонент для рендера. Даже если мы не определяли этот метод, Vue сделает это за нас.

Это значит, когда мы определяем HTML шаблоны в Vue, компилятор шаблонов Vue компилирует их в функцию createElement, принимающую пару параметров и возвращающую результат функции render.

Чтобы поправить код выше, нужно удалить свойство template или тег и определить метод render() в компоненте. Если метод render определен в компоненте, Vue проигнорирует определение шаблона.

... export default { name: 'TextField', render (createElement) { const tag = this.multiline ? 'textarea' : 'input' return createElement(tag, { class: { 'text-input': true, 'is-disabled': false }, attrs: { name: this.name, placeholder: this.placeholder, 'aria-invalid': false } }) } } ...

Что делает код выше:

Метод render принимает хелпер createElement из Vue

Мы программно определяем тег

Далее мы создаем тег и передаем его атрибуты, классы и т.д. в виде объекта. В createElement можно передать лишь пару опций.

Мы возвращаем новый созданный элемент для рендера.

Заметка: все шаблоны, созданные для компонента Vue, будут конвертированы в метод render, который возвращает функцию createElement. Поэтому метод render будет иметь приоритет над определением шаблона.

Разберем пример:

<div> <p>Only you can stop forest fires</p> </div>

Компилятор шаблона конвертирует HTML выше в:

... render (createElement) { return createElement( 'div', {}, createElement( 'p', {}, 'Only you can stop forest fires' ) ) } ...

ОК! Теперь вы спросите: «а разве это не совсем нечитаемо?». Ответ – да. Как только вы определяете компонент с множеством вложенных элементов или парой смежных элементов, мы сталкиваемся с новой проблемой. Мы пожертвовали читаемостью. Как говорится «из огня да в полымя».

Сейчас мы вернем JSX его читаемый вид.

Что такое JSX

Если вы знаете JSX, можете перейти к следующему разделу, где я покажу, как использовать JSX в Vue.

JSX – термин, придуманный командой Facebook.

«JSX – это XML-подобное расширение для JS без определенной семантики.»

JSX не предназначен для реализации движками или браузерами. Вместо этого мы используем транспиллеры типа Babel для перевода JSX в обычный JS.

// this line below is an example of JSX const heading = <h1>Welcome to Scotch</h1>;

JSX позволяет использовать HTML синтаксис в JS.

К сожалению, эта статья предполагает знание JSX, поэтому изучение JSX выходит за рамки статьи. Но я укажу, куда вам нужно двигаться. В JSX очень легко разобраться, это можно сделать за пару минут.

Настройка Vue под использование JSX

Если вы используете Vue-cli 3.0 и выше, то вам повезло, он поддерживает JSX. В более старых версиях Vue-cli можно добавить поддержку, установив babel-preset-vue-app и добавив его в файл .babelrc.

Установка:

# Using npm npm install --save-dev babel-preset-vue-app # Using yarn yarn add --dev babel-preset-vue-app

Файл .babelrc:

{ "presets": ["vue-app"] }

Теперь мы можем использовать JSX в функции render нашего компонента.

Минусы синтаксиса Vue JSX

У JSX в Vue есть несколько минусов.

Первое – вы больше не можете использовать : и @ для привязки и ожидания событий. В синтаксисе JSX они невалидны, и код не пройдет компиляцию.

Чтобы слушать события в JSX, необходимо добавить префикс on. Например, для кликов используйте onClick.

render (createElement) { return ( <button onClick={this.handleClick}></button> ) }

Для модификации событий используйте:

render (createElement) { return ( <button onClick:prevent={this.handleClick}></button> ) }

Для привязки переменной вместо : используйте:

render (createElement) { return ( <button content={this.generatedText}></button> ) }

Чтобы устанавливать HTML строки как контент элемента вместо v-html используйте:

render (createElement) { return ( <button domPropsInnerHTML={htmlContent}></button> ) }

Можно распространять большой объект.

render (createElement) { return ( <button {...this.largeProps}></button> ) }

Использование JSX в рендере

Вернемся к нашему первоначальному TextField компоненту. После активации JSX в Vue приложении мы можем сделать это:

render (createElement) { const inputAttributes = { class: 'input-field has-outline', // class definition onClick: this.handleClick // event handler backdrop: false // custom prop } const inputMarkup = this.multiline ? <textarea {...inputAttributes}></textarea> : <input {...inputAttributes}/> return inputMarkup }

Импорт Vue JSX компонентов

Еще один плюс использования JSX в Vue – больше не нужно регистрировать все компоненты. Просто импортируем и используем.

import {Button} from '../components' export default { render (createElement) { return <Button primary={true}>Edit</Button> } }

Как заставить JSX работать с TypeScript

TypeScript используется как механизм, добавляющий типы в JS. Чтобы добавить поддержку JSX в TypeScript, нужно лишь изменить tsconfig.json. Для активации JSX в TypeScript сохраните файл как .tsx и измените tsconfig.json следующим образом:

{ "compilerOptions": { .... "jsx": "preserve", } }

Установка jsx в значение preserve значит, что TypeScript не должен обрабатывать JSX. Это позволяет Babel взять контроль над JSX и TypeScript, так как он еще не поддерживается в Vue JSX.

Затем создайте файл jsx.d.ts в проекте и добавьте объявления TypeScript JSX для Vue.

import Vue, {VNode} from 'vue' declare global { namespace JSX { interface Element extends VNode {} interface ElementClass extends Vue {} interface ElementAttributesProperty { $props: {} } interface IntrinsicElements { [elemName: string]: any } } }

Проверьте, чтобы TypeScript загрузил файл объявлений. Можно добавить автозагрузку в tsconfig.json через:

{ "compilerOptions": { ... "typesRoot": ["./node_modules/@types", "./types"] } }

Заключение

На сегодня все. Наслаждайтесь парой или всеми Vue.js шаблонами в JSX.

И пожалуйста, не жалуйтесь о том, что JSX ломает SOC (separation of concerns). Я не могу принять еще один из тех аргументов. Если вам нравится использовать функцию createElement с объектами, делайте это!!

Пишите свои мысли и предложения в комментариях.

Автор: Samuel Oloruntoba

Источник: https://scotch.io/

Редакция: Команда webformyself.