JavaScript的React框架中的JSX语法学习入门教程


Posted in Javascript onMarch 05, 2016

什么是JSX?

在用React写组件的时候,通常会用到JSX语法,粗看上去,像是在Javascript代码里直接写起了XML标签,实质上这只是一个语法糖,每一个XML标签都会被JSX转换工具转换成纯Javascript代码,当然你想直接使用纯Javascript代码写也是可以的,只是利用JSX,组件的结构和组件之间的关系看上去更加清晰。

var MyComponent = React.createClass({/*...*/});
var myElement = <MyComponent someProperty={true} />;
React.render(myElement, document.body);

一个XML标签,比如<MyComponent someProperty={true} />会被JSX转换工具转换成什么呢?

比如:

var Nav = React.createClass({/*...*/});
var app = <Nav color="blue"><Profile>click</Profile></Nav>;

会被转化为:

var Nav = React.createClass({/*...*/});
var app = React.createElement(
 Nav,
 {color:"blue"},
 React.createElement(Profile, null, "click")
);

那么也就是说,我们写一个XML标签,实质上就是在调用React.createElement这个方法,并返回一个ReactElement对象。

ReactElement createElement(
 string/ReactClass type,
 [object props],
 [children ...]
)

这个方法的第一个参数可以是一个字符串,表示是一个HTML标准内的元素,或者是一个ReactClass类型的对象,表示我们之前封装好的自定义组件。第二个参数是一个对象,或者说是字典也可以,它保存了这个元素的所有固有属性(即传入后基本不会改变的值)。从第三个参数开始,之后的参数都被认作是元素的子元素。

JSX转化器

要把带有JSX语法的代码转化为纯Javascript代码,有多种方式,对于内联与HTML中的代码或者是未经过转化的外部文件,在script标签中要加上type="text/jsx",并引入JSXTransformer.js文件即可,不过这种方式并不建议在生产环境使用,建议的方法是在代码上线前就将代码转换好,可以使用npm全局安装react-tools:

npm install -g react-tools

并使用命令行工具转化即可(具体用法可以参考jsx -h):

jsx src/ build/

如果使用自动化工具,比如gulp的话,可以使用相应插件gulp-react。

HTML模板中使用JS

在HTML模板中使用JS非常方便,只需要用大括号把JS代码括起来即可。

var names = ['Alice', 'Emily', 'Kate']; 
 
React.render( 
<div> 
{ 
names.map(function (name) { 
return <div>Hello, {name}!</div> 
}) 
} 
</div>, 
document.getElementById('example') 
);

编译出来就变成了这样:

var names = ['Alice', 'Emily', 'Kate']; 
React.render( 
 React.createElement("div", null, names.map(function (name) { 
 return React.createElement("div", null, "Hello, ", name, "!") 
 }) ), 
 document.getElementById('example') 
);

要注意的是,大括号实际就是一个变量输出表达式,JSX最终就是直接把花括号中的内容作为 React.createElement 的第三个参数直接传入了(没有任何修改直接传入),所以其中只能放一行表达式,并且任何不能直接作为第三个参数的写法都是错的,那么你这样写就是错的:

React.render( 
<div> 
{ 
var a = 1; 
names.map(function (name) { 
return <div>Hello, {name}!</div> 
}) 
} 
</div>, 
document.getElementById('example') 
);

因为很明显其中花括号内的内容直接放在第三个参数上,语法不对。

这么写也是错的:

React.render( 
<div> 
{ 
var a = 1; 
 
} 
</div>, 
document.getElementById('example') 
);

因为 React.createElement(“div”, null, var a = 1;) 是语法错误。
那么你也可以理解为什么大括号中的js表达式不能有分号结尾了吧。

需要注意的是,如果你在属性中输出JS变量,是不能加引号的,不然会被当做字符串而不被解析。
应该是这样:

<a title={title}>链接</a>

使用HTML标签

要创建一个HTML标准中存在的元素,直接像写HTML代码一样即可:

var myDivElement = <div className="foo" />;
React.render(myDivElement, document.body);

不过需要注意的是class和for这两个属性,JSX语法最终是要被转换为纯Javascript的,所以要和在Javascript DOM中一样,用className和htmlFor。

还有一点是,在创建HTML标准内的元素时,JSX转化器会丢弃那些非标准的属性,如果一定要添加自定义属性,那么需要在这些自定义属性之前添加data-前缀。

<div data-custom-attribute="foo" />

命名空间式组件

比如开发组件的时候,一个组件有多个子组件,你希望这些子组件可以作为其父组件的属性,那么可以像这样用:

var Form = MyFormComponent;

var App = (
 <Form>
 <Form.Row>
  <Form.Label />
  <Form.Input />
 </Form.Row>
 </Form>
);

这样你只需将子组件的ReactClass作为其父组件的属性:

var MyFormComponent = React.createClass({ ... });

MyFormComponent.Row = React.createClass({ ... });
MyFormComponent.Label = React.createClass({ ... });
MyFormComponent.Input = React.createClass({ ... });

而创建子元素可以直接交给JSX转化器:

var App = (
 React.createElement(Form, null,
  React.createElement(Form.Row, null,
   React.createElement(Form.Label, null),
   React.createElement(Form.Input, null)
  )
 )
);

该功能需要0.11及以上版本

Javascript表达式

在JSX语法中写Javascript表达式只需要用{}即可,比如下面这个使用三目运算符的例子:

// Input (JSX):
var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
// Output (JS):
var content = React.createElement(
 Container,
 null,
 window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
);

不过要注意的是,JSX语法只是语法糖,它的背后是调用ReactElement的构造方法React.createElement的,所以类似这样的写法是不可以的:

// This JSX:
<div id={if (condition) { 'msg' }}>Hello World!</div>

// Is transformed to this JS:
React.createElement("div", {id: if (condition) { 'msg' }}, "Hello World!");

可以从转化后的Javascript代码中看出明显的语法错误,所以要不用三目运算符,要不就这样写:

if (condition) <div id='msg'>Hello World!</div>
else <div>Hello World!</div>

传播属性(Spread Attributes)

在JSX中,可以使用...运算符,表示将一个对象的键值对与ReactElement的props属性合并,这个...运算符的实现类似于ES6 Array中的...运算符的特性。

var props = { foo: x, bar: y };
var component = <Component { ...props } />;

这样就相当于:

var component = <Component foo={x} bar={y} />

它也可以和普通的XML属性混合使用,需要同名属性,后者将覆盖前者:

var props = { foo: 'default' };
var component = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override'
Javascript 相关文章推荐
jQuery 技巧小结
Apr 02 Javascript
javascript在事件监听方面的兼容性小结
Apr 07 Javascript
IE 当eval遇上function的处理
Aug 09 Javascript
c#和Javascript操作同一json对象的实现代码
Jan 17 Javascript
JS+CSS制作DIV层可(最小化/拖拽/排序)功能实现代码
Feb 25 Javascript
js中的json对象详细介绍
Oct 29 Javascript
详解JavaScript中的构造器Constructor模式
Jan 14 Javascript
原生js实现商品放大镜效果
Jan 12 Javascript
jQuery实现的响应鼠标移动方向插件用法示例【附源码下载】
Aug 28 jQuery
微信小程序实现左右列表联动
May 19 Javascript
微信小程序wx.navigateTo方法里的events参数使用详情及场景
Jan 07 Javascript
javscript 数组扁平化的实现
Feb 03 Javascript
在AngularJS框架中处理数据建模的方式解析
Mar 05 #Javascript
简单讲解AngularJS的Routing路由的定义与使用
Mar 05 #Javascript
整理AngularJS框架使用过程当中的一些性能优化要点
Mar 05 #Javascript
详解JavaScript的AngularJS框架中的表达式与指令
Mar 05 #Javascript
深入解析AngularJS框架中$scope的作用与生命周期
Mar 05 #Javascript
JS判断字符串字节数并截取长度的方法
Mar 05 #Javascript
jQuery实现滚动鼠标放大缩小图片的方法(附demo源码下载)
Mar 05 #Javascript
You might like
php你的验证码安全码?
2007/01/02 PHP
PHP 无限分类三种方式 非函数的递归调用!
2011/08/26 PHP
PHP下利用shell后台运行PHP脚本,并获取该脚本的Process ID的代码
2011/09/19 PHP
php+mysqli预处理技术实现添加、修改及删除多条数据的方法
2015/01/30 PHP
Yii2实现上下联动下拉框功能的方法
2016/08/10 PHP
php下载远程大文件(获取远程文件大小)的实例
2017/06/17 PHP
关于全局变量和局部变量的那些事
2013/01/11 Javascript
Javascript中Event属性搜集整理
2013/09/17 Javascript
document节点对象的获取方式示例介绍
2013/12/24 Javascript
js实现动态创建的元素绑定事件
2016/07/19 Javascript
Vue打包后出现一些map文件的解决方法
2018/02/13 Javascript
vue实现a标签点击高亮方法
2018/03/17 Javascript
NodeJS配置CORS实现过程详解
2020/12/02 NodeJs
[38:44]DOTA2上海特级锦标赛A组小组赛#2 Secret VS CDEC第二局
2016/02/25 DOTA
python机器学习之神经网络(一)
2017/12/20 Python
Python cookbook(数据结构与算法)将多个映射合并为单个映射的方法
2018/04/19 Python
Python元组知识点总结
2019/02/18 Python
css3的focus-within选择器的使用
2020/05/11 HTML / CSS
HTML5 本地存储和内容按需加载的思路和方法
2011/04/07 HTML / CSS
HTML5新增加标签和功能概述
2016/09/05 HTML / CSS
英国泰坦旅游网站:全球陪同游览,邮轮和铁路旅行
2016/11/29 全球购物
联想法国官方网站:Lenovo法国
2018/10/18 全球购物
澳大利亚和新西兰最大的在线旅行社之一:Aunt Betty
2019/08/07 全球购物
外企C语言笔试题
2013/11/10 面试题
日语系毕业生推荐信
2013/11/11 职场文书
大学活动邀请函
2014/01/28 职场文书
网络信息安全承诺书
2014/03/26 职场文书
2014年教师节寄语
2014/04/03 职场文书
2014年民主评议党员个人总结
2014/09/24 职场文书
校园游戏活动新闻稿
2014/10/15 职场文书
2015中秋节慰问信范文
2015/03/23 职场文书
2015年出纳年终工作总结
2015/05/14 职场文书
导游词之永济鹳雀楼
2020/01/16 职场文书
关于CSS自定义属性与前端页面的主题切换问题
2022/03/21 HTML / CSS
WCG2010 星际争霸决赛 Flash vs Goojila 1 星际经典比赛回顾
2022/04/01 星际争霸
Java Lambda表达式常用的函数式接口
2022/04/07 Java/Android