本文由笔者翻译自官方文档的JSX In Depth,若干案例经过了改写。其实说白了也好像不算太深入,但还是提示了一些可能的盲区。

JSX是为构造React元素方法React.createElement(component, props, ...children)设计的语法糖。

比方说JSX代码:

<Elem color="red" info="hello">Hello!<Elem/>

用标准的React语法写出来应该是:

React.creatElement({
Elem,
{
color:red,
info:"hello"
},
"Hello!"
});

当没有内容时,根据xml的语法特性,可以加上自闭合标签:

<Elem color="red" info="hello" />

那么React语法是这样:

React.creatElement({
Elem,
{
color:red,
info:"hello"
},
null//啥内容都没有
});

如果你想测试JSX和javascript语法的转换,可以点这里


特殊的React元素规则

JSX标签的第一部分决定了React元素的类型。

JSX标签首字母必须要大写,这样做实际上声明了:这个标签是一个React元素。

这个React标签被编译成一个直接引用命名的变量,因此,当你使用诸如 < Foo / >这样的JSX表达式时,Foo必须在React作用范围内。

必须在React作用范围内

当你用React.createElement调用JSX, 必须引入React库。

例如,下面的每个import都是必要的——尽管React和CustomButton不是直接从JavaScript引用:

import React from 'react';
import CustomButton from './CustomButton'; function WarningButton() {
// return React.createElement(CustomButton, {color: 'red'}, null);
return <CustomButton color="red" />;
}

如果你不使用javascript打包工具或是不在脚本标签引用,上面这种写法就让你的标签就在React的全局作用范围内了。

JSX支持使用点符号

你也可以在React组件的JSX标签中使用点符号(.)。 如果你有一个专门用来输出组件的模块,里面塞满了各种React组件,使用点符号调用会很方便。 比方说,如果MyComponents. DatePicker是一个组件,你可以直接用JSX语法写为:

import React from 'react';

const MyComponents = {
DatePicker: function DatePicker(props) {
return <div>Imagine a {props.color} datepicker here.</div>;
}
} function BlueDatePicker() {
return <MyComponents.DatePicker color="blue" />;
}

用户自定义的组件首字母必须大写

如果一个React元素以小写字母开头,意味着它是一个内置组件(如< div >或< span >)。结果是把一个字符串诸如“div”或“span”传递给React.createElement方法。 如果以大写字母开头,比如< Foo / >编译的结果是:React.createElement(Foo),相应地将生成一个自定义的组件,并导入到你的JavaScript文件中。

请以大写字母命名组件。如果你不方便这么做,那就在使用JSX语法前编译一下你的命名,分配一个大写的变量名。

例如,这段代码将不会像预期的那样运行:

import React from 'react';

// 错了,首字母必须大写
function hello(props) {
// 正确!因为div是html自带的标签
return <div>Hello {props.toWhat}</div>;
} function HelloWorld() {
// 错了,React会把“hello”理解为一个html标签。
return <hello toWhat="World" />;
}

综上,只要把上面代码的hello改为Hello就可以了。

在运行时选择标签名

在React元素里面,你不能使用一般的javascript表达式。如果你想使用一个通用表达式来表示元素,先分配一个大写变量名给它。你渲染一个基于props的组件时,经常会遇到这个问题:

import React from 'react';
import { PhotoStory, VideoStory } from './stories'; const components = {
photo: PhotoStory,
video: VideoStory
}; function Story(props) {
// 错了!JSX不接受表达式
return <components[props.storyType] story={props.story} />;
}

正确的做法是:

...
function Story(props) {
// 对啦。JSX可以接受一个大写开头的变量名
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
}

JSX中的props

有几种不同的方式来指定在JSX中的props。

JavaScript表达式

props可以是任何javascript的表达式——但是得用{ }包起来。 例如,在这JSX中:

var a='zzz';
...
<App name={'xxx'+a+'yyy'}/>

Appprops.name将会计算为xxxzzzyyy

if语句h和for循环不是javascript的表达式,所以你不可以直接把它们作为props的值。相应地,你可以这样做:

...
var a=null; if(this.props.b%2===0){
a=<div>偶数</div>
}else{
a=<div>奇数</div>
}
return (
<div>{this.props.b}是{a}</div>
)
...

字符串字面量

只要不是表达式,你就可以直接传递一个字符串作为props,而不没有用花括号包着。 这两个JSX表达式是等价的:

...
<App name="xxx&lt;yyy"/>
//或者这样
<App name={"xxx>yyy"}>

props默认为True

如果你没有给props传值,那它默认值就是true。如假包换的true。

所以以下两个表达式基本上是等价的

//这样可以
<App name={true}/>
//这样也行
<App name/>

但是第二种用法在ES6语法中容易被混淆为<App name={name}/>,所以不建议这样用。

传播属性

如果你已经把props作为一个对象,你想用JSX统统添加进组件,你可以使用把整个props对象分享出去。 这两个组件是等价的:

//写法1
function App1() {
return <Greeting firstName="Ben" lastName="Hector" />;
}
//写法2:看起来是不是方便了很多呢?
function App2() {
var xxx = {firstName: 'Ben', lastName: 'Hector'};
return <Greeting {...xxx} />;
}

当你构建一个大型的组件盒子,这个方法看起来很好用。但是{...xxx}方法太暴力了,可能一次性给你的组件传递了许多无关紧要的props——从而导致代码混乱。因此在使用前应该慎重。


JSX的children

JSX表达式中,必然包含一个开始标记和结束标记——开始标签和闭合标签之间的内容是一个特殊的props——props.children。有以下几种类型的数据都可以作为children

字符串字面量

如果你在开始标记之间放的是一个字符串,那么你的props.children就是这个字符串——而且还不用打引号。换言之你可以直接塞你需要的html内容:

<App>Hello!</App>

<div>hello!</div>
//看起来和html没区别吧

JSX还可以删除在一行的开始和结束之间的空格。 同时还能删除空白行。 行的相邻标记将被切掉。所以以下写法都一样:

<div>hello world!</div>

<div>hello
world!
</div> <div> hello
world!
</div>

JSX组件的子代

在组件嵌套时,基本上你可以尽情地将子组件加进去。这些嵌套的内容都是props.children

<MyContainer>
<MyFirstComponent />
<MySecondComponent />
</MyContainer> //或者这样
<ul>
<li>haha</li>
<li>hehehe</li>
...
</ul>

但为什么说”基本上“呢?只有一个原则需要把握,就是一个React组件只能返回一个顶层对象——要么就用一个div包起来。这是入门时就反复提及的问题。

javascript表达式

javascript表达式用{}抱起来就可以了。这在遍历方法时非常实用:

var App=React.createClass({
render:function(){
var arr=[];
for(var i=0;i<6;i++){
var content=<li key={i.toString}>我是第{i+1}行</li>
arr.push(content);
} return (
<ul>{arr}</ul>
);
}
});

函数

通常,JavaScript表达式插入JSX,将被解释为一个字符串,或一个React元素,或一串这些东西。 更有趣的是,props.children的行为与其它props没什么不同,不仅可以放用来渲染的内容,还可以放函数,方法。 例如,如果你有一个自定义组件,你可以把props.children作为回调:

var ListTen=React.createClass({
content:function(index){
return (
<div key={index}>这是列表的第{index}项</div>
)
},
render:function(){
return (
<Repeat times={10}>
{this.content}
</Repeat>
);//这里把方法函数content作为一个Repeat组件的props.children }
}); var Repeat=React.createClass({
render:function(){
var arr=[];
for(var i=0;i<this.props.times;i++){
arr.push(this.props.children(i));
}//每循环一次就调用props.children的方法 return (
<div>{arr}</div>
);
}
}); ReactDOM.render(
<ListTen/>,
document.getElementById('example')
);

可见children可以是任何东西——只要React在渲染之前能够理解它。尽管以上代码思路不太常见,但是只要多尝试,就会发现React的内涵。

布尔值,空对象和未定义将被无视

falsenullundefined还有 true 对children来说都是可以放的。但是这对渲染而言没有意义——React在渲染前简单地把他们忽略掉了。所以你用他们企图改变渲染,什么也得不到:

<div />

<div></div>

<div>{false}</div>

<div>{null}</div>

<div>{true}</div>

看起来好像什么都没有用。但这是条件渲染的基本实现思路:

<div>
{showHeader && <Header />}
<Content />
</div

上面的代码中,如果showHeader为false,那它将只执行<Header/>

此外常见的假值中,0是可以被渲染的。

<div>
{props.messages.length &&
<MessageList messages={props.messages} />
}
</div>

如上,如果props.messages不存在,props.messages.length值就为0,结果0就被渲染进去了。

因此,你最好保证你代码中&&的前面是一个布尔值——比如props.messages.length>0就是一个不错的选择。

对于被无视掉的内容,这样写当然是错的:

<div>
true
</div>

对于这个children,你应该这样写——<div>{'true'}</div>,如果是变量,就用字符串方法把它转一下。

深入理解JSX的更多相关文章

  1. 深入理解 JSX

    JSX 是一个看起来很像 XML 的 JavaScript 语法扩展.React 可以用来做简单的 JSX 句法转换. 为什么要使用 JSX? 你不需要为了 React 使用 JSX,可以直接使用纯粹 ...

  2. react脚手架和深入理解jsx语法

    react的mvc和vue的mvvm vue的mvvm属于双向绑定,view层,model数据层,vm实现双向绑定的控制层 此种模式,再某一类项目种很有优势:管理系统 ( OA, ERP , CRM ...

  3. React.js学习之理解JSX和组件

    在开启JSX的学习旅程前,我们先了解一下React的基本原理.React本质上是一个"状态机",它只关心两件事:更新DOM和响应事件,React不处理Ajax.路由和数据存储,也不 ...

  4. React中JSX的理解

    React中JSX的理解 JSX是快速生成react元素的一种语法,实际是React.createElement(component, props, ...children)的语法糖,同时JSX也是J ...

  5. 五分钟学习React(四):什么是JSX

    JSX,即javscript XML,是js内定义的一套XML语法.目前是使用babel作为JSX的编译器.这也是在前几期中载入babel的原因. Facebook引入JSX是为了解决前端代码工程复杂 ...

  6. React 学习(一) ---- React Element /组件/JSX

    学习React的时候,你可能听到最多的就是要先学习webpack, babel,要先学会配置然后才能学react 等等,一堆的配置就把我们吓着了,根本就没有心情就学习react了.其实在最开始学习re ...

  7. React.js 小书 Lesson6 - 使用 JSX 描述 UI 信息

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson6 转载请注明出处,保留原文链接和作者信息. 这一节我们通过一个简单的例子讲解 React.j ...

  8. 使用 JSX 描述 UI 信息

    这一节我们通过一个简单的例子讲解 React.js 描述页面 UI 的方式.把 src/index.js 中的代码改成: import React, { Component } from 'react ...

  9. 1.2 JSX 语法

    官方文档 https://facebook.github.io/react/docs/jsx-in-depth.html JSX 语法听上去很讨厌,但当真正使用的时候会发现,JSX 的写法在组件的组合 ...

随机推荐

  1. JDWP Agent

    JDWP Agent Implementation Description Revision History Disclaimer 1. About this Document 1.1 Purpose ...

  2. Python导入其他文件中的.py文件 即模块

    import sys sys.path.append("路径") import .py文件

  3. Linux基础练习题(二)

    Linux基础练习题(二) 1.复制/etc/skel目录为/home/tuer1,要求/home/tuser1及其内部文件的属组和其它用户均没有任何访问权限. [root@www ~]# cp -r ...

  4. 按照TYPE的文件导入导出功能

    /** * 导入文件Action;*/private File excelFile;// 保存原始文件名private String excelFileFileName;// 保存原始文件名priva ...

  5. BZOJ 2705: [SDOI2012]Longge的问题 [欧拉函数]

    2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 2553  Solved: 1565[Submit][ ...

  6. [LeetCode] Fraction to Recurring Decimal 分数转循环小数

    Given two integers representing the numerator and denominator of a fraction, return the fraction in ...

  7. [LeetCode] Linked List Cycle 单链表中的环

    Given a linked list, determine if it has a cycle in it. Follow up: Can you solve it without using ex ...

  8. OLTP(on-line transaction processing)与OLAP(On-Line Analytical Processing)

    OLTP与OLAP的介绍 数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing).联机分析处理OLAP(On-Line Analytical ...

  9. MobaXterm.9.4|ssh连接工具

    在狂博客中,无意发现的一款集成的远程连接工具MobaXterm.9.4,官方有个人免费版,和企业版!有连接数限制,此款为破解版.感觉还挺不错的,ssh远程连接工具! 01.主界面  02.可选的远程 ...

  10. Scala - 隐式转换和隐式参数

    隐士转换是Scala提供的一种语法糖 Implicit definitions are those that the compiler is allowed to insert into a prog ...