JSX

JSX简介

JSX 是一种用于描述 UIJavaScript 扩展语法,React 使用这种语法描述组件的 UI

长期以来,UI 和数据分离一直是前端领域的一个重要关注点。为了解决这个问题,前端领域发明了模板,将 UI 的定义放入模板文件,将数据的逻辑维护在 JS 代码中,然后通过模板引擎,根据数据和模板文件渲染出最终的 HTML 文件或代码片段。大部分前端框架都实现了自己的模板,要使用这些模板,必须学习它们各自的模板语法,而且对于复杂的 UI,模板语法也很难对其进行清晰的描述。

React 致力于通过组件的概念将页面进行拆分并实现组件复用。React 认为,一个组件应该是具备 UI 描述和 UI 数据的完整体,不应该将它们分开处理,于是发明了 JSX,作为 UI 描述和 UI 数据之间的桥梁。这样,在组件内部可以使用类似 HTML 的标签描述组件的 UI,让 UI 结构直观清晰,同时因为 JSX 本质上仍然是 JavaScript,所以可以使用更多的 JS 语法,构建更加复杂的 UI 结构。

JSX语法

基本语法

JSX 的基本语法和 XML 语法相同,都是使用成对的标签构成一个树状结构的数据,例如:

const element = (
    <div>
        <h1>Hello, world!</h1>
    </div>
)

标签类型

JSX 语法中,使用的标签类型有两种:DOM 类型的标签(divspan 等)和 React 组件类型的标签(在 2.2 节详细介绍组件的概念)。当使用 DOM 类型的标签时,标签的首字母必须小写;当使用 React 组件类型的标签时,组件名称的首字母必须大写React 正是通过首字母的大小写判断渲染的是一个 DOM 类型的标签还是一个 React 组件类型的标签。例如:

// DOM 类型标签
const element = <h1>Hello, world!</h1>

// React 组件类型标签
const element = <HelloWorld />;

// 二者互相嵌套使用
const element = (
    <div>
        <HelloWorld />
    </div>
)

JavaScript表达式

JSX 可以使用 JavaScript 表达式,因为 JSX 本质上仍然是 JavaScript。在 JSX 中使用 JavaScript 表达式需要将表达式用大括号 “{}” 包起来。表达式在 JSX 中的使用场景主要有两个:通过表达式给标签属性赋值和通过表达式定义子组件。例如:

// 通过表达式给标签属性赋值
const element = <MyComponent foo={ 1 + 2 } />

// 通过表达式定义子组件(map虽然是函数,但它的返回值是 JavaScript 表达式)
const todos = ['item1', 'item2', 'item3'];
const element = (
    <ul>
        {todos.map(message => <Item key={message} message={message} />)}
    </ul>
);

注意,JSX 中只能使用 JavaScript 表达式,而不能使用多行 JavaScript 语句。例如,下面的写法都是错误的:

// 错误
const element = <MyComponent foo={const val = 1 + 2; return val; } />

// 错误
let complete;
const element = (
    <div>
        {
            if (complete) {
                return <CompletedList />;
            } else {
                return null;
            }
        }
    </div>
)

不过,JSX 中可以使用三目运算符或逻辑与( && )运算符代替 if 语句的作用。例如:

// 正确
let complete;
const element = (
    <div>
        {
            complete ? <CompletedList /> : null
        }
    </div>
)

// 正确
let complete;
const element = (
    <div>
        {
            complete && <CompletedList />
        }
    </div>
)

标签属性

JSX 标签是 DOM 类型的标签时,对应 DOM 标签支持的属性 JSX 也支持,例如 idclassstyleonclick 等。但是,部分属性的名称会有所改变,主要的变化有:class 要写成 className,事件属性名采用驼峰格式,例如 onclick 要写成 onClick。原因是,classJavaScript 的关键字,所以改成 classNameReactDOM 标签支持的事件重新做了封装,封装时采用了更常用的驼峰命名法命名事件。例如:

<div id='content' className='foo' onClick={()=> {console.log('Hello, React')}} />

JSX 标签是 React 组件类型时,可以任意自定义标签的属性名。例如:

<User name='React' age='4' address='America' >

注释

JSX 中的注释需要用大括号 “{}” 将 /**/ 包裹起来。例如:

const element = (
    <div>
        {/* 这里是一个注释 */}
        <span>React</span>
    </div>
)

JSX不是必需的

JSX 语法对使用 React 来说并不是必需的,实际上,JSX 语法只是 React.createElement(component, props, …​children) 的语法糖,所有的 JSX 语法最终都会被转换成对这个方法的调用。例如:

//JSX语法
const element = <div className='foo'>Hello, React</div>

// 转换后
const element = React.createElement('div', {className: 'foo'}, 'Hello, React')

虽然 JSX 只是一个语法糖,但使用它创建界面元素更加清晰简洁,在项目使用中应该首选 JSX 语法。