React入门0x002: jsx

followWinter

0x000 概述

jsx也是js, 如是说。

0x001 语法

在上文React入门0x001-环境配置和 helloworld中, 出现了一句奇怪的代码:

<h1>Hello, world!</h1>

这在html中没有任何问题,但问题是他出现在了js中,这就是jsx了,它的语法非常简单,却也很神奇:

// 示例,之后会解析
// 保存到变量
let p = <p>this is tag p</p>
// 嵌套
let div = <div>
    {p}
</div>
// 执行语句
let div2 = <div>
{
    div === undefined
        ? <p>undefined</p>
        : {div}
}
</div>

0x002 说明

首先是为什么 js 中能够识别 jsx 呢?这倒不是react的功劳,而是 babel 的功劳,在.babelrc中配置了一个插件:transform-react-jsx,就是这个插件,才能解析jsx,而这个插件是如果和解析的呢?我们可以查看这个插件的文档

  • 输入

    var profile = <div>
      <img src="avatar.png" className="profile" />
      <h3>{[user.firstName, user.lastName].join(' ')}</h3>
    </div>;
  • 输出

    var profile = React.createElement("div", null,
      React.createElement("img", { src: "avatar.png", className: "profile" }),
      React.createElement("h3", null, [user.firstName, user.lastName].join(" "))
    );

其中,jsx中的每一个标签变成了一个 React.createElement(...)函数,而标签的名字,变成了该函数的第一个参数,而img标签的srcclassName等属性变成了该函数的第二个参数,jsx中的嵌套元素,比如div中的imgh3变成了第三个参数。

具体是否是这样,可以编译来看看:

  • 源代码:

    // src/jsx.js
    var user = {
        firstName: "",
        lastName: ""
    }
    var profile = <div>
        <img src="avatar.png" className="profile"/>
        <h3>{[user.firstName, user.lastName].join(' ')}</h3>
    </div>;
  • 编译:

    $ npm install -g babel-cli
    $ babel --plugins transform-react-jsx jsx.js 
    
    "use strict";
    
    var user = {
        firstName: "",
        lastName: ""
    };
    var profile = React.createElement(
        "div",
        null,
        React.createElement("img", { src: "avatar.png", className: "profile" }),
        React.createElement(
            "h3",
            null,
            [user.firstName, user.lastName].join(' ')
        )
    );
    
    

0x003 React.createElement

该函数是由React提供的,所以我们可以看看它的文档说明:

React.createElement(
  type,
  [props],
  [...children]
)

参数:

  • type:类型,可以是一个标签名字,比如pdivhtml标签,也可以是一个React Component,或者React Fragment,具体之后再表。
  • props:属性集合,比如srcclassNamehtml属性(className对应classclass是关键词,所以用className代替),也可以是自定义的属性。
  • childrenReact element子元素集合。

返回值:React element

0x004 总结

jsx只是一层语法糖,在babel的转化下变成了相应的js代码,本质上还是js,所以,在react中用jsx或者不用jsx都是没有本质区别的。上一篇文章中的代码可以改为如下形式:

import React from 'react'
import ReactDom from 'react-dom'

ReactDom.render(
    React.createElement(
        "h1",
        null,
        "Hello, world!"
    ),
    document.getElementById('app')
);

查看浏览器:http://localhost:8080/

clipboard.png

那为什么React推荐构建UI的时候使用jsx,而不是使用js呢,用两种形式实现对比一下就好了

  • React.createElement 形式

    ReactDom.render(
        React.createElement(
            "div",
            null,
            React.createElement(
                "h1",
                null,
                "送方外上人 / 送上人"
            ),
            React.createElement(
                "p",
                null,
                "孤云将野鹤,岂向人间住。莫买沃洲山,时人已知处。"
            )
        ),
        document.getElementById('app')
    )
  • jsx形式

    ReactDom.render(
        <div>
            <h1>送方外上人 / 送上人</h1>
            <p>孤云将野鹤,岂向人间住。莫买沃洲山,时人已知处。</p>
        </div>,
        document.getElementById('app')
    )
    ;

可以看到,使用js形式有太多的'')之类影响布局视觉的符号,相对于html形式的jsx显得繁杂而又不直观,对原本的web开发者也不友好,但这也只是一家之言,flutter在布局方面就采用的代码形式的,视个人爱好而言的东西罢了!

阅读 386

漫漫填坑路,十里长安响码声。
哎,好像不能申请多个专栏呢,原本这个专栏只放前端文章,现在看来不行了!就都放吧!

暂时没有

1.5k 声望
78 粉丝
0 条评论
你知道吗?

暂时没有

1.5k 声望
78 粉丝
宣传栏