Когда React был впервые представлен, одной из функций, привлекших внимание большинства людей (и вызвавших наибольшую критику), был JSX. Если вы изучаете React или когда-либо видели примеры кода, вы, вероятно, перепутали синтаксис. Что это за странное слияние HTML и JavaScript? Это вообще настоящий код?
Давайте посмотрим, что такое JSX, как он работает и почему, черт возьми, мы вообще хотели бы смешивать HTML и JS!
Что такое JSX?
Определенный в документации React как «расширение JavaScript» или «синтаксический сахар для вызова React.createElement(component, props,…children))», JSX — это то, что упрощает написание компонентов React.
JSX считается предметно-ориентированным языком (DSL), который может быть очень похож на язык шаблонов, такой как Mustache, Thymeleaf, Razor, Twig или другие.
Вот пример его синтаксиса:
const element = <h1>Hello, World!</h1>;
То, что идет после знака равенства, не является строкой или HTML, а скорее JSX. Он не отображается напрямую в HTML, а вместо этого отображает классы React, которые потребляются виртуальной DOM. В конце концов, благодаря таинственной магии Virtual DOM, он попадет на страницу и будет преобразован в HTML.
Как это работает?
JSX по-прежнему остается просто JavaScript с некоторыми дополнительными функциями. С помощью JSX вы можете писать код, очень похожий на HTML или XML, но при этом у вас есть возможность беспрепятственно смешивать методы и переменные JavaScript в своем коде. JSX интерпретируется транспилером, таким как Babel, и преобразуется в код JavaScript, который может понять UI Framework (в данном случае React).
Примечание: вы можете использовать Babel REPL для преобразования любого из следующих примеров в обычный JavaScript.
Не нравится JSX? Это классно. Технически это не требуется, и документы React фактически включают раздел об использовании React Without JSX. Но позвольте мне предупредить вас прямо сейчас, это некрасиво. Не верите мне? Посмотри.
JSX:
class SitePoint extends Component { render() { return ( <div>My name is <span>{this.props.myName}</span></div> ) } }
React Sans JSX:
class SitePoint extends Component { render() { return React.createElement( "div", null, "My name is", React.createElement( "span", null, this.props.myName ) ) } }
Конечно, глядя на эти небольшие фрагменты кода на этой странице, вы можете подумать: «О, это не так уж плохо, я мог бы это сделать». Но можете ли вы представить себе такое приложение целиком?
Пример — всего лишь два простых вложенных элемента HTML, ничего особенного. По сути, просто вложенный Hello Worldэквивалент. Попытка написать приложение React без JSX потребует очень много времени, и, если вы, как и большинство из нас, других разработчиков, работающих здесь персонажами в DevLand ™, очень вероятно, быстро превратится в запутанный беспорядок из спагетти-кода. Фу!
Использование фреймворков, библиотек и тому подобного призвано облегчить, а не усложнить нашу жизнь. Я уверен, что мы все видели чрезмерное использование и злоупотребление библиотеками или фреймворками в нашей карьере, но использование JSX с вашим React определенно не один из таких случаев.
Зачем использовать JSX?
Есть несколько причин, по которым JSX — хорошая идея:
У него низкий входной барьер. JSX настолько близок к обычному HTML и CSS, насколько это возможно в настоящее время. С помощью JSX вы можете легко встраивать фрагменты JavaScript в свои шаблоны без необходимости изучать дополнительный язык шаблонов и иметь дело со сложными уровнями абстракции. У любого человека, знакомого с HTML, CSS и JavaScript, не должно возникнуть проблем с чтением и пониманием шаблонов JSX.
Поддержка TypeScript. TypeScript поддерживает компиляцию файлов TSX с проверкой типов. Это означает, что если вы ошиблись в названии элемента или типа атрибута, компиляция завершится неудачно, и вы увидите сообщение об ошибке, указывающее на вашу ошибку. Популярные IDE, такие как VS Code, также поддерживают файлы TSX и предоставляют автозавершение кода, рефакторинг и другие полезные функции.
Безопасность. JSX решает обычные проблемы очистки вывода, чтобы предотвратить такие атаки, как межсайтовый скриптинг.
А как насчет разделения проблем?
Широко распространено мнение, что смешивание HTML и JavaScript нарушает священный принцип разделения проблем. Это суждение предполагает, что существует четкое разделение между HTML, который отвечает за представление, и JavaScript, который отвечает за приложение и бизнес-логику. Однако это разделение основано на технологиях, а не на их заботах. JavaScript, отвечающий за визуализацию списка элементов, по-прежнему принадлежит уровню представления и должен располагаться ближе к шаблону, чем к остальной части приложения.
Используя JavaScript, мы принимаем тот факт, что граница должна проводиться не между HTML и JavaScript, а скорее между логикой представления и логикой приложения, независимо от языков, используемых с обеих сторон. Сосредоточение внимания на этом не позволяет нам смешивать презентационный JavaScript с бизнес-логикой, тем самым обеспечивая разделение задач, уменьшая взаимосвязь и улучшая ремонтопригодность.
Использование JSX с React
Начнем с основ. Как упоминалось ранее, JSX необходимо преобразовать в обычный JavaScript, прежде чем его можно будет отобразить в браузере. Поэтому, если вы хотите следовать примерам, у вас должно быть уже настроено приложение React.
Все следующие примеры поставляются с работающими демонстрациями CodePen, поэтому, если все, что вам нужно, — это быстро поиграть с кодом, это может быть для вас хорошим вариантом.
В противном случае вы можете выбрать инструмент Facebook Create React App. Чтобы использовать это, вам необходимо установить Node и npm. Если нет, перейдите на страницу загрузки Node.js и скачайте последнюю версию для своей системы (npm поставляется в комплекте с Node). Кроме того, вы можете обратиться к нашему руководству по установке Node с помощью диспетчера версий.
Установив Node, вы можете создать новое приложение React следующим образом:
npx create-react-app myapp
Это создаст myappпапку. Перейдите в эту папку и запустите сервер разработки следующим образом:
cd myapp npm start
Откроется ваш браузер по умолчанию, и вы увидите свое новое приложение React. В рамках этого руководства вы можете работать в Appкомпоненте, который находится по адресу src/App.js.
Теперь перейдем к коду.
Основные выражения
JSX очень похож на простой HTML и использует тот же синтаксис на основе XML. Вот канонический пример «Hello, World» для начала:
const element = <h1>Hello, World!</h1>; ReactDOM.render(element, document.getElementById('root'));
Обратите внимание, как <h1> элемент используется непосредственно внутри обычного JavaScript. Вокруг него нет кавычек, поскольку это не строка, а языковое выражение.
Точно так же вы можете использовать JavaScript в тегах JSX, заключив их в фигурные скобки:
function getGreeting(name) { return `Hello, ${name}`; } const element = <h1>{getGreeting('John')}</h1>; ReactDOM.render(element, document.getElementById('root'));
Вы также можете использовать выражения JavaScript при указании значений атрибутов, например, при передаче объекта, содержащего встроенные стили в этом примере. Это полезно, когда вы хотите передать значение динамического атрибута:
const styles = { color: 'red', fontStyle: 'italic' } const element = <h1 style={styles}>Hello, World!</h1>; ReactDOM.render(element, document.getElementById('root'));
Примечание: если вам нужно передать список динамических атрибутов, вы можете использовать оператор распространения: <h1 {...attributes}></h1
Конечно, как и в случае с обычным HTML, элементы JSX могут содержать дочерние элементы. Это могут быть строковые литералы, другие элементы или выражения JavaScript:
function getGreeting() { return ( <h2>Welcome to the website</h2> ) } const element = <div> <h1>Hello!</h1> {getGreeting()} </div>; ReactDOM.render(element, document.getElementById('root'));
Условные утверждения
Тот факт, что вы можете встраивать выражения JavaScript и передавать элементы JSX, открывает множество возможностей для структурирования вашего кода. Частым вариантом использования является условное отображение элемента для вошедшего в систему пользователя, например персонализированное сообщение, или ошибка проверки. JSX не поддерживает стандартные ifоператоры, но вы можете использовать тернарный оператор:
const loggedIn = true; const element = <div> <h1>Hello!</h1> <h2> {(loggedIn) ? 'Welcome back' : 'Nice to meet you'} </h2> </div>; ReactDOM.render(element, document.getElementById('root'));
Выражение может вернуться false, true, nullили, undefinedчтобы избежать рендеринга элемента. Возврат некоторых ложных значений, таких как 0или пустая строка, по-прежнему будет отображать элемент:
const error = true; const element = <div> <label> Name: <input /> {error ? <div style={{color: 'red'}}>Name invalid</div> : null} </label> </div>; ReactDOM.render(element, document.getElementById('root'));
Обратите внимание на двойные фигурные скобки, используемые в style атрибуте. Это синтаксис для передачи встроенного объекта в качестве значения: внешняя пара обозначает выражение, а внутренняя — сам объект.
В приведенном выше фрагменте мы видим следующее:
{error ? <div style={{color: 'red'}}>Name invalid</div> : null}
Это можно сократить еще больше:
{error && <div style={{color: 'red'}}>Name invalid</div>}
Это работает, потому что в JavaScript true && expression всегда оценивается expressionи false && expressionвсегда оценивается как false.
Но хотя этот шаблон довольно распространен, не забывайте о удобочитаемости. Придерживайтесь соглашений о коде, которые согласованы и понятны вашей команде. Также не переусердствуйте с вложением условных конструкций. Часто люди вставляют один тернарный оператор в другой, чтобы сэкономить пару строк кода за счет удобочитаемости. Выполните рефакторинг такого кода, выделив блоки в отдельные переменные или функции.
Loops
Другой частый вариант использования — отображение списка повторяющихся элементов. В JSX вы не можете использовать forциклы, но вы можете перебирать массив с помощью метода array map (). Например, вот простой способ визуализировать список элементов:
const items = [ 'Bread', 'Milk', 'Eggs' ] const element = <div> Grocery list: <ul> {items.map(item => <li>{item}</li>)} </ul> </div>; ReactDOM.render(element, document.getElementById('root'));
Очевидно, что вы можете использовать в коде и другие методы массива, и может возникнуть соблазн проскользнуть в логику фильтрации или другие вычисления. Не поддавайся этому! Помните принцип разделения задач и отделите эту логику от кода рендеринга. Это упростит чтение, понимание и тестирование кода.
Пользовательские компоненты
Два предстоящих раздела более специфичны для React, но все же стоит обсудить их, чтобы получить хорошее представление о том, как все сочетается друг с другом.
Предыдущие примеры кода чрезвычайно упрощены, поскольку они отображают только небольшой набор стандартных элементов HTML. На самом деле ваше приложение будет состоять из настраиваемых компонентов, которые будут содержать ваше представление и логику для конкретного приложения. React позволяет определять пользовательские компоненты и использовать их в разметке как обычные элементы HTML. Пользовательский элемент может быть определен либо как функция, либо как класс ES6.
Примечание: согласно соглашениям об именах React, пользовательские элементы должны начинаться с заглавной буквы, чтобы отличать их от стандартных элементов.
function FunctionComponent() { return <h2>This is a function component.</h2> } class ClassComponent extends React.Component { render() { return <h2>This is a class component.</h2> } } const element = <div> <FunctionComponent /> <ClassComponent /> </div>; ReactDOM.render(element, document.getElementById('root'));
Обработка событий
JSX предоставляет способ привязки событий, аналогичный обычному HTML. Вы можете определить свойство для элемента (те же имена свойств, что и для обычного HTML, но с верблюжьей структурой) и передать функцию в качестве значения. В React функция обратного вызова получит объект SyntheticEvent в качестве первого параметра, который является абстракцией поверх обычного объекта события браузера:
function handleEvent(e) { alert('Button clicked!'); console.log(e); } const element = <button onClick={handleEvent}>Test click</button>; ReactDOM.render(element, document.getElementById('root'));
Примечание: обратите внимание на значение thisпри передаче обработчиков событий. Когда вы определяете свой компонент как класс ES6, вы обычно определяете обработчики событий как методы класса. Методы, передаваемые по значению, не привязаны к определенному thisзначению, поэтому для сохранения текущего контекста их необходимо явно привязать. См . Документацию React для получения более подробной информации о том, как это сделать.
Не только для React
JSX с React — отличная штука. Но что, если вы используете другой фреймворк или библиотеку, но все равно хотите их использовать? Что ж, вам повезло — потому что JSX технически не привязан к React. Это все еще просто DSL или «синтаксический сахар», помните? Вот еще несколько проектов, использующих JSX:
- Вы можете использовать JSX в renderфункции Vue с помощью предустановки @ vue / babel-preset-jsx Babel.
- Некоторые другие фреймворки, которые позиционируют себя как минималистичные React-совместимые альтернативы, такие как Preact, Inferno или Hyperapp, используют JSX для своего уровня рендеринга.
- MDX позволяет использовать JSX в файлах Markdown для добавления интерактивных элементов JS.
Я надеюсь, что это введение в JSX помогло вам лучше понять, что такое JSX, как он может вам помочь и как его можно использовать для создания ваших приложений. А теперь возвращайся и сделай крутые штуки!