JSX 的由来与语法

  1. JSX 由来
    1. React 通过创建虚拟元素来管理整个虚拟 DOM
      1. 1 DOM 元素
      2. 2 组件元素
  2. JSX 语法
    1. 标签
    2. 属性
      1. 布尔属性
    3. 组件名的命名空间
    4. JSX 内的注释
    5. HTML 转义

为什么 React 需要 JSX

JSX 由来

React 通过创建虚拟元素来管理整个虚拟 DOM

虚拟元素与真实元素是对应的,它的构建和更新在内存中完成(废,过程不会反映给真实 DOM。
React 的虚拟元素分为:1-DOM 类。2 - 组件类。这些元素与 JSX 密切联系。
在 JSX 代码中,组件的 tag 名是大写字母开头,而那些 DOM 标签的 tag 名则以小写字母开头。

1 DOM 元素

一个 Web 页面由 HTML 元素嵌套组合,使用 JS 怎么描述这个嵌套?
我们可以使用简单的 JSON 完成。
例如,一个按钮的 HTML 代码:

<button class="btn btn-blue">
    <em>Confirm</em>
</button>

使用 JSON 表示这个按钮:

{
    type: 'button',
    props: {
        className: 'btn btn-blue',
        // 子元素可以是一个数组
        children: [
            {
            type: 'em',
            props: {
                children: 'Confirm'
            }
            },
        ]
    }
}

这样就可以在 JS 中创建虚拟 DOM 元素了。
这些对象表示的元素就可以指示 React 如何去显示真实的 DOM。

2 组件元素

既然可以用 JS 代码表示 DOM 元素了,那就可以进一步封装上面的” 虚拟 DOM“按钮。

const Button = ({ color, text }) => {
    return {
        type: 'button',
        // 属性又是一个对象
        props: {
            className: `btn btn-${color}`,
            // 按钮的子元素是一个字符串
            children: {
                type: 'em',
                props: {
                    children: text
                }
            }
        }
    }
}

我们可以很方便地调用 Button({ color:'red', text:'ENG' }) 生成一个按钮实例。
再想一想,其实还可以通过 ** 标签的方式 ** 创建一个按钮实例,标签名就是 Button,标签的元素属性就是参数,此时就具备了标签名,属性这两大条件,这样的方式构建的元素称为 组件元素

这也是 React 的核心思想之一。因为有公共的表达方法,我们就可以让元素们彼此嵌套或混合。这些层层封装的组件元素,就是所谓的 React 组件,最终我们可以用递归渲染的方式构建出完全的 DOM 元素树。

可以以这个按钮最为原型,继承出更多按钮。
例如,封装一个表示危险操作的按钮:

const DangerButton = ({ text }) => (
    {
        type: Button,
        props: {
            // 红色的按钮
            color: 'red',
            children: text
        }
    }
)

接着,我们可以很轻松地运用它,继续封装新的组件元素:

const DeleteAccount = () => {
    type: 'div',
    props: {
        className: 'delete-account',
        children: [
            {
                type: 'p',
                props: {
                    children: '确定吗?'
                }
            },
            {
                type: Deletebutton,
                props: {
                    children: '确定'
                }
            }
        ]
    }
}

这个 DeleteAccount 只有两个子元素,就显得比较冗余,当遇到更大的组件,就难以阅读了。
这让我们想起使用 HTML 书写结构时的畅快感受,JSX 语法为此应运而生。假如我们使用 JSX 语法来重新表达上述组件元素,只需这么写:

const DeleteAccount = () => {
    <div>
        <p > 确定吗?</p>
        <DangerButton > 确定 </DangerButton>
        </div>
}

JSX 将 HTML 语法直接加入到 JavaScript 代码中,再通过翻译器(babel)转换到纯 JavaScript 后由浏览器执行。
JSX 的出现为我们省去了这个烦琐过程,使用 JSX 写法的代码更易于阅读与开发。


JSX 语法

标签

  • 定义标签时,有且只能有一个标签包裹 JSX 结构。因为这些 JSX 要被使用 React.createElement 调用,最外层没有被包裹,显然无法转译成方法调用。
  • 标签必须闭合

属性

HTML 存在的那些标签,在 JSX 里的属性不变,class 和 for 除外。

由于 JSX 内可以写 JS 代码和 HTML 代码,但是 HTML 的 for class 和 JS 关键字冲突,所以将 HTML 代码的 for class 改为 htmlFor className

HTML 类标签的 data- 自定义属性也是有效的。

组件标签的属性是完全自定义的属性,也可以理解为实现组件所需要的参数。

布尔属性

布尔属性如果缺值,则默认是 true
例如,<CheckBox checked={true} /> 可以简写属性为 <CheckBox checked/>

组件名的命名空间

  • JSX 可以使用命名空间,解决组件名称相同问题。
    const App = () => (
      <MUI.PaisedButton label="Default" />
    );

JSX 内的注释

虽然 JSX 里可以写 JS,但是与 JSX 注释与 JS 不同。
在标签外,可以在 { /**/ } 内写那种多行注释,不能写单行注释。
在组件标签内,可以直接写多行注释

const App = (
    <Nav>
        {/* 节点注释 */}
        <Person
            /* 多行
            注释 */
            name={window.isLoggedIn ? window.name : ''}
        />
    </Nav>
);

HTML 转义

一些 HTML 实体字符无法被正确显示。例如 &copy;
有几种解决办法:

  • 直接使用 UTF-8 字符 ©;
  • 使用对应字符的 Unicode 编码查询编码;
  • 使用数组组装 <div>{['cc', <span>&copy;</span>, '2015']}</div>;
  • 直接插入原始的 HTML

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论。
我的空间