迹忆客 专注技术分享

当前位置:主页 > 学无止境 > WEB前端 >

JavaScript 与 JSX 有什么不同

作者:迹忆客 最近更新:2022/05/08 浏览次数:

当大家开始学习 React 时,先遇到的事情之一是 JSX,这是我们定义 React 组件的基本方式。 但是什么是 JSX,它与 JavaScript 相比如何? 在本教程中,我们将揭示有关 JSX 的所有信息,以及使用它时需要记住的事项。


JSX 是什么?

JSX 代表 JavaScript XML。 它是 JavaScript 的语法扩展,可让我们在 JavaScript 文件中使用 HTML 标记。 我们可以使用类似于 XML 的语法创建元素,而不是通过 JavaScript 对象创建、配置和附加 HTML 标记,该语法将为我们在幕后生成 DOM 元素。

那么它看起来怎么样呢? 让我们看一个简单的例子:

const jsx = <div>Welcome to React</div>;

如何使用 JSX

那么如何在实践中使用 JSX? JSX 很灵活,但它们也需要遵循某些规则。 让我们一一回顾它的特点和规则。 首先,您可以在 JSX 中使用 JavaScript 表达式。

在 JSX 中使用表达式

假设我们想在 HTML 模板中使用 JavaScript 变量。 使用花括号,可以对它们进行插值以获得动态行为:

const name = 'World';
const expression = <h1>Hello {name}</h1>;

这里 {name} 将替换为 h1 元素中的单词“World”。 当然,我们不仅可以嵌入 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 us",
            "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>;

表达式还可用于创建 if 语句或使用三元运算符根据变量的值返回不同的 HTML 元素。 对于这些,通常使用短路:

{/* 如果有 `name` 变量,则输出信息 */}
{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 属性,我们可以:

{/* Invalid */}
<div aria-label="Label"></div>
<div aria-checked="true"></div>
<div tab-index="0"></div>

{/* Valid */}
<div ariaLabel="Label"></div>
<div ariaChecked="true"></div>
<div tabIndex="0"></div>

在 JSX 中使用属性时也有一个特殊的例外,那就是使用 HTML 类。 由于单词 class 是 JavaScript 中的保留关键字,我们需要使用 className 代替:

{/* 无效 - class 是保留的关键字 */}
<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>The HTML layout for the slider</div>
);

// 稍后在应用程序中,可以使用函数名称引用此函数:
<Slider />

此外,请确保函数大写,否则,它将被视为 HTML 元素。 一个例外是使用对象方法,例如:

onst component = {
    slider() {
        return <div>The HTML layout for the slider</div>
    }
};

<component.slider />

通过使用函数,我们还可以传递可用于 HTML 元素的道具:

const Slider = ({ size }) => (
    <div className={size}>The HTML layout for the slider</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 不是一个有效的HTML元素

<Component />
React.createElement(Component); // 函数被引用

<component.slider />
React.createElement(component.slider); // 方法被引用

总结

总的来说,JSX 可以帮助我们简化代码,使其更易于使用,同时也使其更具可读性。 回顾一下本章的重要部分,以下是关于 JSX 与 JavaScript 连接的一些注意事项:

  • JSX 是 JavaScript 的语法扩展,代表 JavaScript XML。
  • 可以使用或不使用 JSX 来编写 React。 尽管为了自己的理智,强烈建议使用 JSX。
  • JSX 通过使用花括号来支持表达式的使用。
  • JSX 中的属性是用驼峰命名法编写的。
  • JSX 元素必须始终关闭。 如果不涉及子元素,则元素必须是自闭合的。
  • 一次只能返回一个 JSX。 如果需要返回多个元素,请使用片段。
  • 函数可以返回 JSX 元素。
  • JSX 是为 React.createElement 函数调用生成的。

话虽如此,现在我们已经了解了有关 JSX 及其与 JavaScript 的相关性的所有信息。

除非注明转载,本站文章均为原创或翻译,欢迎转载,转载请以链接形式注明出处

本文地址:

迹忆客

专注技术分享,项目实战分享!

技术宅 乐于分享 7年编程经验
社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

热门文章

教程更新

热门标签

扫码一下
查看教程更方便