深入理解JSX
本文由笔者翻译自官方文档的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'}/>
App
的props.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<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的内涵。
布尔值,空对象和未定义将被无视
false
, null
, undefined
还有 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的更多相关文章
- 深入理解 JSX
JSX 是一个看起来很像 XML 的 JavaScript 语法扩展.React 可以用来做简单的 JSX 句法转换. 为什么要使用 JSX? 你不需要为了 React 使用 JSX,可以直接使用纯粹 ...
- react脚手架和深入理解jsx语法
react的mvc和vue的mvvm vue的mvvm属于双向绑定,view层,model数据层,vm实现双向绑定的控制层 此种模式,再某一类项目种很有优势:管理系统 ( OA, ERP , CRM ...
- React.js学习之理解JSX和组件
在开启JSX的学习旅程前,我们先了解一下React的基本原理.React本质上是一个"状态机",它只关心两件事:更新DOM和响应事件,React不处理Ajax.路由和数据存储,也不 ...
- React中JSX的理解
React中JSX的理解 JSX是快速生成react元素的一种语法,实际是React.createElement(component, props, ...children)的语法糖,同时JSX也是J ...
- 五分钟学习React(四):什么是JSX
JSX,即javscript XML,是js内定义的一套XML语法.目前是使用babel作为JSX的编译器.这也是在前几期中载入babel的原因. Facebook引入JSX是为了解决前端代码工程复杂 ...
- React 学习(一) ---- React Element /组件/JSX
学习React的时候,你可能听到最多的就是要先学习webpack, babel,要先学会配置然后才能学react 等等,一堆的配置就把我们吓着了,根本就没有心情就学习react了.其实在最开始学习re ...
- React.js 小书 Lesson6 - 使用 JSX 描述 UI 信息
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson6 转载请注明出处,保留原文链接和作者信息. 这一节我们通过一个简单的例子讲解 React.j ...
- 使用 JSX 描述 UI 信息
这一节我们通过一个简单的例子讲解 React.js 描述页面 UI 的方式.把 src/index.js 中的代码改成: import React, { Component } from 'react ...
- 1.2 JSX 语法
官方文档 https://facebook.github.io/react/docs/jsx-in-depth.html JSX 语法听上去很讨厌,但当真正使用的时候会发现,JSX 的写法在组件的组合 ...
随机推荐
- 自动化集成部署udeployer 批量统一安装一键部署
通过jenkins构建项目:version版本控制:udployer自动化集成:ucop业务巡检做到高效高可用的自动化体系. 1.0版本: 逻辑与业务分离,完美实现逻辑与业务分离,业务实现统一sh ...
- 架构从最简单的数据访问框架(ORM)到资源调度和治理中心(SOA)说起
随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进. 单一应用架构当网站流量很小时,只需一个应用,将 ...
- ASP.NET MVC 5 03 - 安装MVC5并创建第一个应用程序
不知不觉 又逢年底, 穷的钞票 所剩无几. 朋友圈里 各种装逼, 抹抹眼泪 MVC 继续走起.. 本系列纯属学习笔记,如果哪里有错误或遗漏的地方,希望大家高调指出,当然,我肯定不会低调改正的.(开个小 ...
- 关于Http状态码
Http状态码表示Http协议所返回的响应的状态.比如客户端向服务器发送请求,如果成功的获得请求的资源,则返回的状态码为200,表示相应成功.如果请求的资源不存在,则通常返回404错误. Http状态 ...
- ASP.NET MVC Filters 4种默认过滤器的使用【附示例】
过滤器(Filters)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,不是每个请求都会响应内容,只响应特定内容给那些有特定权限的用户,过滤器理论上有以下功能: 判断 ...
- Spring, MyBatis 多数据源的配置和管理
同一个项目有时会涉及到多个数据库,也就是多数据源.多数据源又可以分为两种情况: 1)两个或多个数据库没有相关性,各自独立,其实这种可以作为两个项目来开发.比如在游戏开发中一个数据库是平台数据库,其它还 ...
- 开发常用图标png、ico 图标下载
推荐几个不错的下载地址: 1.http://www.easyicon.net/ 2.http://588ku.com/sucai/ 3.http://www.iconpng.com 可直接下载png等 ...
- cg数据类型
Cg 支持7 种基本的数据类型:1. float,32 位浮点数据,一个符号位.浮点数据类型被所有的profile 支持(但是DirectX8 pixel profiles 在一些操作中降低了浮点数的 ...
- [LeetCode] Self Crossing 自交
You are given an array x of n positive numbers. You start at point (0,0) and moves x[0] metres to th ...
- [LeetCode] Find Median from Data Stream 找出数据流的中位数
Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...