过去半年基本都是使用VUE来开发项目,也有了一定的经验了,后续将会推出一套前后端完整的基于VUE的管理系统。从今天开始学习 React ,首先就从定义React组件的JSX开始。那什么是JSX呢?与JavaScript有啥关系?本文就来一起学习。
JSX到底是什么?
JSX,即 JavaScript XML,JavaScript 的语法扩展,允许在 JavaScript 文件中编写 HTML (这是个人内心抗拒的原因)。不必通过 JavaScript 对象创建、修改或者拼接 HTML ,可以使用类似 XML 的语法创建元素,编译运行时生成相应的 DOM 元素。
那它看起来怎么样?请看下面的代码:
const jsx = <div>Hello React</div>;
如何使用JSX?
那么如何在实践中使用JSX呢?JSX是灵活的,不管哪种编程方式,都需要遵循一定的规则。下面就来逐一介绍。
在JSX中使用表达式
假设希望在HTML模板中使用JavaScript变量,使用花括号 {}
,可以插值变量以获得动态值:
const title = "DevPoint";
const expression = <h1>Hello {title}</h1>;
这里 {title}
将在 h1
元素中替换为 DevPoint
。当然,不仅可以嵌入JavaScript变量,还可以使用更复杂的表达式:
const a = 1;
const b = 1;
const expression = (
<code>
{a} + {b} = {a + b}
</code>
);
这将输出1+1=2
,在处理数组时,表达式也通常用于生成HTML元素列表。假设有一个动态菜单,从API接收数据:
{
"menu": [
{
"name": "Home",
"link": "/"
},
{
"name": "About",
"link": "/about"
},
{
"name": "Contact",
"link": "/contact"
}
]
}
然后,可以使用JSX表达式映射整个数组:
const menu = <ul>{menu.map((item) => console.log(item))}</ul>;
在这里,使用JSX表达式中的 Array.map
方法将每个元素记录到控制台,但是如何显示列表元素呢?
const menu = (
<ul>
{menu.map((item) => (
<li>
<a href={item.link}>{item.name}</a>
</li>
))}
</ul>
);
可以简单地从函数返回所需的元素,这相当于在下面显式写出 return
关键字:
const menu = (
<ul>
{menu.map((item) => {
return (
<li>
<a href={item.link}>{item.name}</a>
</li>
);
})}
</ul>
);
表达式还可用于创建条件语句,或使用三元运算符根据变量的值返回不同的HTML元素,如下:
{
name && <h1>Hello {name}</h1>;
}
{ /* 这里是注释 */}
{
name ? <h1>Hello {name}</h1> : null;
}
如上所见,JSX中的注释也用于表达式中。如果要在一行前面写//
的话,它也会被打印到最终的HTML文件中,因为它被解释为自由流文本。因此,在使用注释时需要使用表达式。
在JSX中使用属性
正如上面所看到的,也可以像平常一样在JSX元素中使用HTML属性。还可以对属性使用JSX表达式,或者如果使用的是静态值,则可以使用常规HTML中的引号来定义它们:
<a href={item.link} target="_blank">
{item.name}
</a>;
在JSX中,这些称为 props
,需要注意的一点是,当涉及到使用破折号的属性时,JSX 使用驼峰大小写。例如,如果要添加 aria
属性,将执行以下操作:
<div aria-label="Label"></div>
<div aria-checked="true"></div>
<div tab-index="0"></div>
<div ariaLabel="Label"></div>
<div ariaChecked="true"></div>
<div tabIndex="0"></div>
在JSX中使用属性时还有一个特殊的例外,那就是使用HTML类。由于单词 class
在JavaScript中是一个保留关键字,因此需要改用 className
:
<div class="carousel"></div>
<div className="carousel"></div>
始终关闭JSX标记
当使用自动关闭标记或使用纯粹用于传递视觉信息的元素且这些元素没有任何子元素时,请确保始终关闭标签,否则,将会出现错误:
{/* 错误的方式 */}
<br>
<img>
<div>
{/* 正确的方式 */}
<br />
<img />
<div className="loader" />
返回JSX
需要指出的另一条重要规则是,一次只能返回一个JSX元素。请看下面的 HTML 元素:
<span className="tooltip">...</span>
<div className="tooltip-backdrop" />
这个例子是无效的,因为试图返回多个相邻的JSX元素,为了修复它,需要将其包装在父级中:
<span className="tooltip-container">
<span className="tooltip">...</span>
<div className="tooltip-backdrop" />
</span>
或者,如果不想用不必要的HTML元素污染DOM树,还可以使用一个称为片段的特殊标记:
<React.Fragment>
<span className="tooltip">...</span>
<div className="tooltip-backdrop" />
</React.Fragment>
{/* 或者 */}
<Fragment>
<span className="tooltip">...</span>
<div className="tooltip-backdrop" />
</Fragment>
{/* 或者 */}
<>
<span className="tooltip">...</span>
<div className="tooltip-backdrop" />
</>
以上三个示例将生成相同的代码,都能正常运行,并且不会向HTML文件中添加额外的DOM元素。
存储JSX
JSX元素也可以存储在变量中,并传递给其它JSX元素使用。但是,很可能会涉及到将JSX元素存储在函数中的情况:
const Slider = () => (
<div>这是一个组件</div>
);
<Slider />
此外,建议将函数大写,否则,它将被视为HTML元素,例外的情况是使用对象方法,例如:
const component = {
slider() {
return <div>这是一个组件</div>
}
};
<component.slider />
通过使用函数,还可以传递可用于HTML元素的插件:
const Slider = ({ size }) => (
<div className={size}>这是一个可以控制尺寸的组件</div>
);
<Slider size="large" />
<Slider size="medium" />
<Slider size="small" />
如上所见,不仅限于使用HTML属性的名称,还可以使用自定义名称。
JSX生成成什么?
那么JSX究竟生成了什么呢?浏览器无法理解JSX语法,因此 React 需要将其编译为浏览器能够理解的 JavaScript 函数调用。这些JavaScript函数调用最终将创建和更新必要的HTML元素。以下面的代码片段为例,它将生成以下函数调用:
const jsx = <div>Welcome to React</div>;
React.createElement("div", null, "Welcome to React");
const jsx = <div className="carousel" />;
React.createElement("div", { className: "carousel" });
如果 JSX 元素有子元素,那么这些子元素也将被编译为 React.createElement
调用,并最终生成在 JavaScript 包中,如下:
React.createElement(component, props, ...children);
同样,如果对组件使用小写,则这些组件将被视为HTML元素,因此请确保将它们大写:
<component />;
React.createElement("component");
<Component />;
React.createElement(Component);
<component.slider />;
React.createElement(component.slider);
总结
JSX 可以简化代码,使其更易于使用,同时也使其更具可读性。为了回顾本教程的重要部分,关于 JSX 与 JavaScript 的连接,以下是一些注意事项:
- JSX 是 JavaScript 的语法扩展,代表 JavaScript XML。
- React 可以使用或不使用 JSX 编写,尽管如此,强烈建议使用 JSX。
- JSX 支持使用大括号来使用表达式。
- JSX 中的属性是用驼峰命名法编写的。
- JSX 元素必须始终关闭。如果不涉及子元素,则元素必须是闭合(成对)的。
- 一次只能返回一个 JSX,如果需要返回多个元素,请使用片段。
- 函数可以返回 JSX 元素。
- JSX 生成为
React.createElement
函数调用。