写点什么

了解学习 JSX 的工作方式

作者:devpoint
  • 2021 年 12 月 06 日
  • 本文字数:3055 字

    阅读完需:约 10 分钟

了解学习 JSX 的工作方式

过去半年基本都是使用 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 的连接,以下是一些注意事项:


  1. JSX 是 JavaScript 的语法扩展,代表 JavaScript XML。

  2. React 可以使用或不使用 JSX 编写,尽管如此,强烈建议使用 JSX。

  3. JSX 支持使用大括号来使用表达式。

  4. JSX 中的属性是用驼峰命名法编写的。

  5. JSX 元素必须始终关闭。如果不涉及子元素,则元素必须是闭合(成对)的。

  6. 一次只能返回一个 JSX,如果需要返回多个元素,请使用片段。

  7. 函数可以返回 JSX 元素。

  8. JSX 生成为 React.createElement 函数调用。

发布于: 5 小时前阅读数: 7
用户头像

devpoint

关注

细节的追求者 2011.11.12 加入

专注前端开发,用技术创造价值!

评论

发布
暂无评论
了解学习 JSX 的工作方式