JSX入门

JSX是React引入的一项技术。让我们深入研究

JSX简介

JSX是React引入的一项技术。

尽管React无需使用JSX即可完全正常工作,但这是处理组件的理想技术,因此React从JSX中受益匪浅。

最初,您可能会认为使用JSX就像将HTML和JavaScript(以及您将看到的CSS)。

但这是不正确的,因为使用JSX语法时,您实际上正在写有关组件UI应该是什么的声明性语法。

而且您正在描述的UI不是使用字符串,而是使用JavaScript,这使您可以做很多事情。

JSX入门

这是定义包含字符串的h1标签的方法:

const element = <h1>Hello, world!</h1>

它看起来像JavaScript和HTML的奇怪组合,但实际上,它们全都是JavaScript。

看起来像HTML的实际上是用于定义组件及其在标记内的位置的语法糖。

在JSX表达式中,可以很容易地插入属性:

const myId = 'test'
const element = <h1 id={myId}>Hello, world!</h1>

您只需要在属性带有破折号(-),而是将其转换为camelCase语法,以及以下2种特殊情况:

  • class变成className
  • for变成htmlFor

因为它们是JavaScript中的保留字。

这是一个JSX代码段,将两个组件包装到一个div标签:

<div>
  <BlogPostsList />
  <Sidebar />
</div>

始终需要关闭标签,因为XML比HTML多(如果您还记得XHTML的日子,这会很熟悉,但是从那时起,HTML5宽松的语法就赢了)。在这种情况下,使用自动关闭标签。

请注意,我是如何将2个组件包装到一个div。为什么?因为render()函数只能返回一个节点,因此,如果您要返回2个同级,只需添加一个父级即可。它可以是任何标签,而不仅仅是div

转译JSX

浏览器无法执行包含JSX代码的JavaScript文件。必须首先将它们转换为常规JS。

如何?通过执行一个称为转堆

我们已经说过JSX是可选的,因为对于每条JSX行,都可以使用相应的普通JavaScript替代品,这就是JSX被移植到的内容。

例如,以下两个构造是等效的:

普通JS

ReactDOM.render(
  React.createElement('div', { id: 'test' },
    React.createElement('h1', null, 'A title'),
    React.createElement('p', null, 'A paragraph')
  ),
  document.getElementById('myapp')
)

JSX

ReactDOM.render(
  <div id="test">
    <h1>A title</h1>
    <p>A paragraph</p>
  </div>,
  document.getElementById('myapp')
)

这个非常基本的示例只是起点,但是您已经可以看到,与使用JSX相比,普通的JS语法要复杂得多。

在撰写本文时,最流行的方式是移植是用巴别塔,这是运行时的默认选项create-react-app,因此,如果您使用它,则不必担心,一切都会在您的幕后发生。

如果你不使用create-react-app您需要自己设置Babel。

JSX中的JS

JSX接受任何类型的JavaScript混合。

每当您需要添加一些JS时,只需将其放在花括号中{}。例如,以下是使用在其他地方定义的常量值的方法:

const paragraph = 'A paragraph'
ReactDOM.render(
  <div id="test">
    <h1>A title</h1>
    <p>{paragraph}</p>
  </div>,
  document.getElementById('myapp')
)

这是一个基本的例子。大括号接受任何JS代码:

const paragraph = 'A paragraph'
ReactDOM.render(
  <table>
    {rows.map((row, i) => {
      return <tr>{row.text}</tr>
    })}
  </table>,
  document.getElementById('myapp')
)

如你看到的我们将JavaScript嵌套在JSX内,将其嵌套在JSX中。您可以根据需要进行深入研究。

JSX中的HTML

JSX非常类似于HTML,但实际上是XML语法。

最后,您呈现HTML,因此您需要了解如何在HTML中定义某些内容与如何在JSX中定义它们之间的一些区别。

您需要关闭所有标签

就像在XHTML中一样,如果您曾经使用过它,则需要关闭所有标签:不再<br>而是使用自动关闭标签:<br />(其他标签也是如此)

camelCase是新标准

在HTML中,您会发现没有任何大小写的属性(例如,onchange)。在JSX中,它们被重命名为其等效的camelCase:

  • onchange=>onChange
  • onclick=>onClick
  • onsubmit=>onSubmit

class变成className

由于JSX是JavaScript,class是保留字,你不能写

<p class="description">

但是你需要使用

<p className="description">

同样适用于for被翻译成htmlFor

样式属性更改其语义

styleHTML中的属性允许指定内联样式。在JSX中,它不再接受字符串,而在React中的CSS您会明白为什么这是一个非常方便的更改。

形式

表单字段定义和事件在JSX中进行了更改,以提供更多的一致性和实用性。

JSX中的表单详细介绍表格。

React中的CSS

JSX提供了一种定义CSS的好方法。

如果您对HTML内联样式有一点经验,乍一看就会发现自己落后了10或15年,进入了内联CSS完全正常的世界(如今已经被妖魔化了,通常只是“快速修复”)解决方案)。

JSX样式不是一回事:首先,JSX而不是接受包含CSS属性的字符串style属性仅接受一个对象。这意味着您在对象中定义属性:

var divStyle = {
  color: 'white'
}

ReactDOM.render(<div style={divStyle}>Hello World!</div>, mountNode)

或者

ReactDOM.render(<div style={{ color: 'white' }}>Hello World!</div>, mountNode)

您在JSX中编写的CSS值与普通CSS略有不同:

  • 键属性名称为camelCased
  • 值只是字符串
  • 您用逗号分隔每个元组

为什么相对于普通CSS / SASS / LESS,这是首选?

CSS是一个未解决的问题。自成立以来,围绕它的数十种工具先涨后跌。 CSS的主要问题是没有作用域,并且很容易编写不以任何方式强制执行的CSS,因此“快速修复”会影响不应被触及的元素。

JSX允许组件(例如在React中定义)完全封装其样式。

这是首选解决方案吗?

除非需要,否则JSX中的内联样式会很好。

  1. 撰写媒体查询
  2. 样式动画
  3. 参考伪类(例如:hover
  4. 参考伪元素(例如::first-letter

简而言之,它们涵盖了基础知识,但这不是最终的解决方案。

JSX中的表单

JSX对HTML表单的工作方式进行了一些更改,目的是使开发人员更轻松。

valuedefaultValue

value属性始终保存该字段的当前值。

defaultValue属性包含创建字段时设置的默认值。

这有助于解决常规的一些怪异行为DOM检查时的互动input.valueinput.getAttribute('value')返回一个当前值和一个原始默认值。

这也适用于textarea领域,例如

<textarea>Some text</textarea>

但反而

<textarea defaultValue={'Some text'} />

为了select字段,而不是使用

<select>
  <option value="x" selected>
    ...
  </option>
</select>

使用

<select defaultValue="x">
  <option value="x">...</option>
</select>

更一致的onChange

将功能传递给onChange属性,您可以订阅表单字段上的事件。

即使在各个领域,它也能一致地工作radioselectcheckbox输入字段触发onChange事件。

onChange在输入字符时也会触发input或者textarea场地。

JSX自动转义

为了减轻XSS漏洞的风险,JSX强制表达式自动转义。

这意味着在字符串表达式中使用HTML实体时,您可能会遇到问题。

您希望以下内容能够打印© 2020

<p>{'&copy; 2020'}</p>

但这不是,它是印刷品&copy; 2020因为该字符串已转义。

要解决此问题,您可以将实体移到表达式外:

<p>&copy; 2020</p>

或者使用一个常量来打印与您需要打印的HTML实体相对应的Unicode表示形式:

<p>{'\u00A9 2020'}</p>

JSX中的空白

要在JSX中添加空格,有2条规则:

Horizontal white space is trimmed to 1

如果同一行中的元素之间有空格,则所有空格都将修剪为1个空格。

<p>Something       becomes               this</p>

变成

<p>Something becomes this</p>

消除了垂直空白

<p>
  Something
  becomes
  this
</p>

变成

<p>Somethingbecomesthis</p>

要解决此问题,您需要通过添加如下所示的空格表达式来显式添加空格:

<p>
  Something
  {' '}becomes
  {' '}this
</p>

或通过将字符串嵌入空格表达式中:

<p>
  Something
  {' becomes '}
  this
</p>

在JSX中添加评论

您可以使用表达式中的普通JavaScript注释向JSX添加注释:

<p>
  {/* a comment */}
  {
    //another comment
  }
</p>

传播属性

在JSX中,常见的操作是为属性分配值。

而不是手动进行操作,例如

<div>
  <BlogPost title={data.title} date={data.date} />
</div>

你可以通过

<div>
  <BlogPost {...data} />
</div>

以及data借助ES6,该对象将自动用作属性点差算子

如何在JSX中循环

如果您需要循环生成一组JSX局部元素,则可以创建一个循环,然后将JSX添加到数组中:

const elements = [] //..some array

const items = []

for (const [index, value] of elements.entries()) { items.push(<Element key={index} />) }

现在,当渲染JSX时,您可以嵌入items通过将其包装在花括号中来排列数组:

const elements = ['one', 'two', 'three'];

const items = []

for (const [index, value] of elements.entries()) { items.push(<li key={index}>{value}</li>) }

return ( <div> {items} </div> )

您可以直接在JSX中执行以下操作:map而不是for-of循环:

const elements = ['one', 'two', 'three'];
return (
  <ul>
    {elements.map((value, index) => {
      return <li key={index}>{value}</li>
    })}
  </ul>
)

免费下载我的反应手册


更多反应教程: