React
JSX
Поиск…
замечания
JSX - это шаг препроцессора, который добавляет синтаксис XML к JavaScript. Вы можете определенно использовать React без JSX, но JSX делает React намного более элегантным.
Подобно XML, теги JSX имеют имя, атрибуты и дочерние элементы. Если значение атрибута заключено в кавычки, значение представляет собой строку. В противном случае оберните значение в фигурные скобки, а значение - вложенное выражение JavaScript.
По сути, JSX просто предоставляет синтаксический сахар для функции React.createElement(component, props, ...children)
.
Итак, следующий код JSX:
class HelloMessage extends React.Component {
render() {
return <div>Hello {this.props.name}</div>;
}
}
ReactDOM.render(<HelloMessage name="Kalo" />, mountNode);
Скомпилируется до следующего кода JavaScript:
class HelloMessage extends React.Component {
render() {
return React.createElement(
"div",
null,
"Hello ",
this.props.name
);
}
}
ReactDOM.render(React.createElement(HelloMessage, { name: "Kalo" }), mountNode);
В заключение отметим, что следующая строка в JSX не является ни строкой, ни HTML :
const element = <h1>Hello, world!</h1>;
Он называется JSX, и это расширение синтаксиса JavaScript . JSX может напомнить вам о языке шаблонов, но он поставляется с полной мощью JavaScript.
Команда React говорит в своих документах, что они рекомендуют использовать ее для описания того, как должен выглядеть пользовательский интерфейс.
Подставки в JSX
Существует несколько способов указать реквизиты в JSX.
Выражения JavaScript
Вы можете передать любое выражение JavaScript в качестве опоры, окружив его {}
. Например, в этом JSX:
<MyComponent count={1 + 2 + 3 + 4} />
Внутри MyComponent
значение props.count
будет равно 10
, потому что вычисляется выражение 1 + 2 + 3 + 4
.
Если утверждения и циклы не являются выражениями в JavaScript, поэтому они не могут использоваться в JSX напрямую.
Строковые литералы
Конечно, вы можете просто передать любой string literal
в качестве prop
. Эти два выражения JSX эквивалентны:
<MyComponent message="hello world" />
<MyComponent message={'hello world'} />
Когда вы передаете строковый литерал, его значение не привязано к HTML. Таким образом, эти два выражения JSX эквивалентны:
<MyComponent message="<3" />
<MyComponent message={'<3'} />
Такое поведение обычно не имеет значения. Это только упоминается здесь для полноты.
Значение по умолчанию для реквизита
Если вы не передадите значение для пропеллера, оно по умолчанию равно true
. Эти два выражения JSX эквивалентны:
<MyTextBox autocomplete />
<MyTextBox autocomplete={true} />
Тем не менее, команда React говорит в своих документах, используя этот подход, не рекомендуется , потому что его можно путать с сокращением объекта ES6 {foo}
который меньше для {foo: foo}
а не {foo: true}
. Они говорят, что это поведение существует именно так, чтобы оно соответствовало поведению HTML.
Атрибуты распространения
Если у вас уже есть реквизит в качестве объекта, и вы хотите передать его в JSX, вы можете использовать ...
в качестве оператора распространения для передачи всего объекта реквизита. Эти два компонента эквивалентны:
function Case1() {
return <Greeting firstName="Kaloyab" lastName="Kosev" />;
}
function Case2() {
const person = {firstName: 'Kaloyan', lastName: 'Kosev'};
return <Greeting {...person} />;
}
Дети в JSX
В выражениях JSX, которые содержат как открытый тег, так и закрывающий тег, контент между этими тегами передается как специальный prop: props.children
. Есть несколько способов передачи детей:
Строковые литералы
Вы можете поместить строку между открывающими и закрывающими тегами, а props.children
будет только той строкой. Это полезно для многих встроенных элементов HTML. Например:
<MyComponent>
<h1>Hello world!</h1>
</MyComponent>
Это действительный JSX, а props.children
в MyComponent будет просто <h1>Hello world!</h1>
.
Обратите внимание, что HTML не привязан , поэтому вы можете вообще писать JSX так же, как и писать HTML.
Заметим, что в этом случае JSX:
- удаляет пробелы в начале и в конце строки;
- удаляет пустые строки;
- удаляются новые строки, смежные с тегами;
- новые строки, которые встречаются в середине строковых литералов, сводятся в одно пространство.
Дети JSX
Вы можете предоставить больше JSX-элементов в качестве детей. Это полезно для отображения вложенных компонентов:
<MyContainer>
<MyFirstComponent />
<MySecondComponent />
</MyContainer>
Вы можете смешивать разные типы детей, поэтому вы можете использовать строковые литералы вместе с детьми JSX . Это еще один способ, в котором JSX похож на HTML, так что это как действительный JSX, так и действительный HTML:
<div>
<h2>Here is a list</h2>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
Обратите внимание, что компонент React не может возвращать несколько элементов React, но одно выражение JSX может иметь несколько дочерних элементов . Поэтому, если вы хотите, чтобы компонент отображал несколько вещей, вы можете обернуть их в div
как пример выше.
Выражения JavaScript
Вы можете передать любое выражение JavaScript в виде дочерних элементов, заключая его в {}
. Например, эти выражения эквивалентны:
<MyComponent>foo</MyComponent>
<MyComponent>{'foo'}</MyComponent>
Это часто полезно для отображения списка выражений JSX произвольной длины. Например, это отображает список HTML:
const Item = ({ message }) => (
<li>{ message }</li>
);
const TodoList = () => {
const todos = ['finish doc', 'submit review', 'wait stackoverflow review'];
return (
<ul>
{ todos.map(message => (<Item key={message} message={message} />)) }
</ul>
);
};
Обратите внимание, что выражения JavaScript могут быть смешаны с другими типами детей.
Функции как дети
Обычно выражения JavaScript, вставленные в JSX, будут оценивать строку, элемент React или список этих вещей. Тем не менее, props.children
работает так же, как и любая другая поддержка в том, что он может передавать любые данные, а не только те виды, которые React знает, как визуализировать. Например, если у вас есть пользовательский компонент, вы можете заставить его выполнить обратный вызов как props.children
:
const ListOfTenThings = () => (
<Repeat numTimes={10}>
{(index) => <div key={index}>This is item {index} in the list</div>}
</Repeat>
);
// Calls the children callback numTimes to produce a repeated component
const Repeat = ({ numTimes, children }) => {
let items = [];
for (let i = 0; i < numTimes; i++) {
items.push(children(i));
}
return <div>{items}</div>;
};
Дети, переданные в пользовательский компонент, могут быть чем угодно, если этот компонент преобразует их во что-то, что Реакт может понять перед рендерингом. Это использование не является обычным явлением, но оно работает, если вы хотите расширить возможности JSX.
Игнорируемые значения
Обратите внимание, что false
, null
, undefined
и true
являются действительными дочерними. Но они просто не делают. Эти выражения JSX будут отображать одно и то же:
<MyComponent />
<MyComponent></MyComponent>
<MyComponent>{false}</MyComponent>
<MyComponent>{null}</MyComponent>
<MyComponent>{true}</MyComponent>
Это чрезвычайно полезно для условного рендеринга элементов React. Этот JSX отображает только if, если showHeader
имеет значение true:
<div>
{showHeader && <Header />}
<Content />
</div>
Одним из важных предостережений является то, что некоторые «фальшивые» значения, такие как 0
, все еще выдаются React. Например, этот код не будет вести себя так, как вы могли ожидать, потому что 0
будет напечатан, если props.messages
- пустой массив:
<div>
{props.messages.length &&
<MessageList messages={props.messages} />
}
</div>
Один из подходов к исправлению заключается в том, чтобы убедиться, что выражение перед &&
всегда является логическим:
<div>
{props.messages.length > 0 &&
<MessageList messages={props.messages} />
}
</div>
Наконец, не забывайте, что если вы хотите, чтобы в выводе было указано значение false
, true
, null
или undefined
, вы должны сначала преобразовать его в строку:
<div>
My JavaScript variable is {String(myVariable)}.
</div>