本文由笔者翻译自官方文档的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. ASP.NET MVC 5 04 - 控制器

    PS: 唉.本来这一篇前几天早就应该发了的,可是谁每月没有那么几天啊... 呵呵.开个玩笑.反正就是各种烦气,所以也就一直没上来继续发了. 年底了,摆正一下心态吧.好好干,整点钱,过年回家能跟亲朋好友 ...

  2. Django模板的继承

    一.extend 1.extend继承模板 2.一个文件中只能继承一个模板 3.extend继承模板中的所有内容,模板的内容包括:html的head和body ,eg:

  3. XML中的转义字符

    HTML中<, >,&等有特别含义,(前两个字符用于链接签,&用于转义),不能直接使用.使用这三个字符时,应使用他们的转义序列,如下所示: & 或 & &a ...

  4. DIV宽度设置成100%,浏览器窗口缩小后,右边出现留白

    解决办法:给body添加min-width属性

  5. 【码在江湖】前端少侠的json故事(上)日月第一击

    日月第一击 这是我前端生涯第一次和后台对接,其经历真是苦不堪言,多次绝处逢生,柳暗花明,可就是迟迟见不到那条村子.当然,最后我还是完成了这次对接.下面来聊一聊我这白痴一般的经历. 序章 话说天下大势, ...

  6. [转]Writing Custom Middleware in ASP.NET Core 1.0

    本文转自:https://www.exceptionnotfound.net/writing-custom-middleware-in-asp-net-core-1-0/ One of the new ...

  7. 项目游戏开发日记 No.0x000005

    14软二杨近星(2014551622) 还有一周就要交项目了, 看着周围的人也都忙碌了起来, 看着大部分人的项目都已经初具容貌, 我们团队里面也搞得人心惶惶, 一来是, 时间不多了, 还有很多事情要做 ...

  8. struts2中各个jar包作用

    Struts2.3.4 所需的Jar包及介绍 Jar包的分类 jar包名称 jar包版本 jar包 文件名 jar包 的作用 jar包内包含的主要包路径及主要类 依赖的自有jar包名称 依赖的第三方j ...

  9. 【repost】JS原型与原型链终极详解

    一. 普通对象与函数对象  JavaScript 中,万物皆对象!但对象也是有区别的.分为普通对象和函数对象,Object ,Function 是JS自带的函数对象.下面举例说明 function f ...

  10. [LeetCode] Range Sum Query 2D - Mutable 二维区域和检索 - 可变

    Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...