【二】React之JSX
疯子我是个医生,有疯子开的证明
一、 使用JSX
利用 JSX 编写 DOM 结构,可以用原生的 HTML 标签,也可以直接像普通标签一样引用 React 组件。这两者约定通过大小写来区分,小写的字符串是 HTML 标签,大写开头的变量是 React 组件。
使用HTML标签:
import React from 'react';
import { render } from 'react-dom';
var myDivElement = <div className="foo" />;
render(myDivElement,document.getElementById('mountNode'));
HTML 里的 class 在 JSX 里要写成 className,因为 class 在 JS 里是保留关键字。同理某些属性比如for 要写成 htmlFor。
使用组件:
import React from 'react';
import { render } from 'react-dom';
import MyComponent from './MyComponet';
var myElement = <MyComponent someProperty={true}>
render(myElement,document.body);
二、 使用JavaScript 表达式
属性值使用表达式,只要用 { } 替换 " ":
// Input (JSX):
var person = <Person name={window.isLoggedIn ? window.name : ''} />;
// Output (JS):
var person = React.createElement(
Person,
{name: window.isLoggedIn ? window.name : ''}
);
子组件也可以作为表达式使用:
// 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)
);
三、注释
沿用 JavaScript,唯一要注意的是在一个组件的子元素位置使用注释要用 { } 包起来。
var content = (
<Nav>
{/* child comment, put {} around */}
<Person
/* multi
line
comment */
name={window.isLoggedIn ? window.name : ''} // end of line comment
/>
</Nav>
);
四、转义
React 会将所有要显示到 DOM 的字符串转义,防止 XSS。所以如果 JSX 中含有转义后的实体字符比如(& copy;) (©) 最后显示到 DOM 中不会正确显示,因为 React 自动把 © 中的特殊字符转义了。有几种解决办法:
- 直接使用 UTF-8 字符 ©
- 使用对应字符的 Unicode 编码,查询编码
- 使用数组组装 <div>{['cc ', <span>©</span>, ' 2015']}</div>
- 直接插入原始的 HTML
<div dangerouslySetInnerHTML={{__html: 'cc © 2015'}} />
五、自定义HTML属性
如果在 JSX 中使用的属性不存在于 HTML 的规范中,这个属性会被忽略。如果要使用自定义属性,可以用 data- 前缀。可访问性属性的前缀 aria-
也是支持的。
支持的标签和属性
如果你要使用的某些标签或属性不在这些支持列表里面就可能被 React 忽略,必须要使用的话可以提 issue,或者用前面提到的 dangerouslySetInnerHTML
。
六、属性扩散
给组件设置多个属性或者甚至不知道这些属性的名称,这时候 spread attributes 功能就很有用了。
比如:
var props = {};
props.foo = x;
props.bar = y;
var component = <Component {...props} />;
props对象的属性会被设置成Component的属性。
属性也可以被覆盖:
var props = { foo: 'default' };
var com ponent = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override' 后面的属性值会覆盖前面的属性
七、关于 ... 操作符
ES6语法中:
展开语法(Spread syntax), 可以在函数调用/数组构造时, 将数组表达式或者string在语法层面展开;还可以在构造字面量对象时, 将对象表达式按key-value的方式展开。(注: 字面量一般指 [1, 2, 3] 或者 {name: "mdn"} 这种简洁的构造方式)
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers));
// expected output: 6
console.log(sum.apply(null, numbers));
// expected output: 6
ES7语法中:
剩余属性:接收其余的变量,类似python中的**kwargs
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x; // 1
y; // 2
z; // { a: 3, b: 4 }
延伸属性:将枚举的值赋值到变量上
let n = { x, y, ...z};
n; // { x: 1,y: 2, a: 3, b: 4 }
八、JSX与HTML的差异
- 注意保留关键字起名不能冲突,例如:class要写成className
- style 属性接收由CSS属性构成的JS对象
- onChange 事件表现更接近我们的直觉(不需要onBlur去触发)
- 表单的表现差异比较大
更多异同,可以参见 DOM Differences
注:onblur 事件会在对象失去焦点时发生。onblur 事件在用户离开输入框时执行 JavaScript 代码