一、什么是JSX
使用JSX声明一个变量(React 当中的元素):
const element = Hello, world!
;
JSX是一种 JavaScript 的语法扩展。 我们推荐在 React 中使用 JSX 来描述用户界面。JSX 乍看起来可能比较像是模版语言,但事实上它完全是在 JavaScript 内部实现的。
二、为什么要使用JSX
传统的 MVC 是将模板放在其他地方,比如
2. 外联方式载入
即将 JSX 代码单独放在一个.jsx 文件中。
ReactDOM.render(
hello hangge.com
,
document.getElementById('example')
);
然后在页面上通过下面的方式引入这个 .jsx 文件。
四、在 JSX 中使用表达式
可以任意地在 JSX 当中使用 JavaScript 表达式,在 JSX 当中的表达式要包含在大括号里(个人理解就是写在JS里的HTML里的JS需要{}大括号)。
// 定义一个函数,返回传入的名字的拼写后的结果
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
// 定义一个数据类型为对象的常量
const user = {
firstName: 'Harper',
lastName: 'Perez'
};
// 使用JSX语法来定义一个html标签(所以element为小写开头)
const element = (
Hello, {formatName(user)}!
);
// 渲染这个html标签
ReactDOM.render(
element,
document.getElementById('root')
);
注意:
- 我们书写 JSX 的时候一般都会带上换行和缩进,这样可以增强代码的可读性。
- 与此同时,我们同样推荐在 JSX 代码的外面扩上一个小括号,这样可以防止 分号自动插入 的 bug。
五、JSX 本身其实也是一种表达式
在编译之后呢,JSX 其实会被转化为普通的 JavaScript 对象。
这也就意味着,你其实可以在 if 或者 for 语句里使用 JSX,将它赋值给变量,当作参数传入,作为返回值都可以:
// 定义一个函数,如果有传参数进来就把名字拼写好返回,否则就返回陌生人
function getGreeting(user) {
if (user) {
return Hello, {formatName(user)}!
;
}
return Hello, Stranger.
;
}
六、JSX 属性
- 你可以使用引号来定义以字符串为值的属性:
const element = ;
- 也可以使用大括号来定义以 JavaScript 表达式为值的属性:
const element = ;
切记使用了大括号包裹的 JavaScript 表达式时就不要再到外面套引号了。JSX 会将引号当中的内容识别为字符串而不是表达式。(不要src="{user.avatarUrl}",会以为src为{user.avatarUrl})
七、JSX 嵌套
如果 JSX 标签是闭合式的,那么你需要在结尾处用/>
, 就好像 XML/HTML 一样:
const element = ;
JSX 标签同样可以相互嵌套:(当换行和缩进的时候,使用括号包住它们)
const element = (
Hello!
Good to see you here.
);
警告:
因为 JSX 的特性更接近 JavaScript 而不是 HTML , 所以 React DOM 使用camelCase
小驼峰命名 来定义属性的名称,而不是使用 HTML 的属性名称。(概括就是: JSX使用小驼峰命名定义属性的名称)
例如,class
变成了className
,而tabindex
则对应着tabIndex
。
八、JSX 防注入攻击
你可以放心地在 JSX 当中使用用户输入:
const title = response.potentiallyMaliciousInput;
// 直接使用是安全的:
const element = {title}
;
React DOM 在渲染之前默认会 过滤 所有传入的值。它可以确保你的应用不会被注入攻击。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(跨站脚本) 攻击。
九、HTML 转义
React 会将所有要显示到 DOM 的字符串转义,防止 XSS。所以如果 JSX 中含有转义后的实体字符比如 ©
(©) 最后显示到 DOM 中不会正确显示,因为 React 自动把 ©
中的特殊字符转义了。有几种解决办法:
- 直接使用 UTF-8 字符 ©
- 使用对应字符的 Unicode 编码,查询编码
- 使用数组组装 {['cc ', ©, ' 2015']}
- 直接插入原始的 HTML
十、JSX 代表 Objects
Babel 转译器会把 JSX 转换成一个名为React.createElement()
的方法调用。
下面两种代码的作用是完全相同的:
const element = (
Hello, world!
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
React.createElement() 这个方法首先会进行一些避免bug的检查,之后会返回一个类似下面例子的对象:
// 注意: 以下示例是简化过的(不代表在 React 源码中是这样)
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world'
}
};
这样的对象被称为 “React 元素”
。它代表所有你在屏幕上看到的东西。
React 通过读取这些对象来构建 DOM 并保持数据内容一致。
十一、注释
在 JSX 里使用注释也很简单,就是沿用 JavaScript,唯一要注意的是在一个组件的子元素位置使用注释要用 {} 包起来。
var content = (
);
十二、自定义 HTML 属性
如果在 JSX 中使用的属性不存在于 HTML 的规范中,这个属性会被忽略。如果要使用自定义属性,可以用 data-
前缀。
可访问性属性的前缀 aria-
也是支持的。
支持的标签和属性
如果你要使用的某些标签或属性不在这些支持列表里面就可能被 React 忽略,必须要使用的话可以提 issue,或者用前面提到的 dangerouslySetInnerHTML
。
十三、属性扩散
有时候你需要给组件设置多个属性,你不想一个个写下这些属性,或者有时候你甚至不知道这些属性的名称,这时候 spread attributes 的功能就很有用了。
比如:
var props = {};
props.foo = x;
props.bar = y;
var component = ;
props 对象的属性会被设置成 Component 的属性。
属性也可以被覆盖:
ar props = { foo: 'default' };
var component = ;
console.log(component.props.foo); // 'override'
写在后面的属性值会覆盖前面的属性。
关于
...
操作符
The...
operator (or spread operator) is already supported for arrays in ES6. There is also an ES7 proposal for Object Rest and Spread Properties.
参考资料
- React 官方中文文档
- React 中文文档
- React - JSX语法详解(附样例)