React
- 把用户界面抽象成一个个组件
- 复用组件方式:引入 JSX 语法
- 能开发浏览器、原生移动应用
搭配
- Flux
- Redux
- GraphQL/Relay
Virtual DOM
image.png-
每次数据更新后,重新计算 Virtual DOM,并和上一次生成的 Virtual DOM 做对比,对发生变化的部分做批量更新。
-
直接提供 shouldComponentUpdate 生命周期方法,来减少数
据变化后不必要的 Virtual DOM 对比过程,以保证性能。
函数式编程
- 声明式编程: 模仿自己逻辑思考方式
- React 把过去不断重复构建 UI 的过程抽象成了组件
JSX 语法
基于DOM的封装
1、原始DOM
<button class="btn btn-blue">
<em>Confirm</em>
</button>
2、转化成json对象:
{
type: 'button',
props: {
className: 'btn btn-blue',
children: [{
type: 'em',
props: {
children: 'Confirm'
}
}]
}
}
3、封装成组件
const Button = ({ color, text }) => {
return {
type: 'button',
props: {
className: `btn btn-${color}`,
children: {
type: 'em',
props: {
children: text,
},
},
},
};
}
4、jsx语法:
const DeleteAccount = () => (
<div>
<p>Are you sure?</p>
<DangerButton>Confirm</DangerButton>
<Button color="blue">Cancel</Button>
</div>
);
将 HTML 语法直接加入到 JavaScript 代码中,再通过翻译器转换到纯
JavaScript 后由浏览器执行。JSX 在产品打包阶段都已经编译成纯 JavaScript
DeleteAccount 组件通过 Babel 转译成 React 可以执行的代码
var DeleteAccount = function DeleteAccount() {
return React.createElement(
'div',
null,
React.createElement(
'p',
null,
'Are you sure?'
),
React.createElement(
DangerButton,
null,
'Confirm'
),
React.createElement(
Button,
{ color: 'blue' },
'Cancel'
)
);
元素属性
- class 属性改为 className
- for 属性改为 htmlFor
1、展开属性
const component = <Component name={name} value={value} />;
2、设置 props
const component = <Component />;
component.props.name = name;
component.props.value = value;
3、
const data = { name: 'foo', value: 'bar' };
const component = <Component name={data.name} value={data.value} />;
等价于
const data = { name: 'foo', value: 'bar' };
const component = <Component {...data} />;
- 自定义 HTML 属性
1、原始DOM
<div d="xxx">content</div>
2、要使用 data- 前缀
<div data-attr="xxx">content</div>
3、自定义标签中任意的属性都是被支持的
<x-my-component custom-attr="foo" />
- 组件的最终目的是输出虚拟元素,需要被渲染到界面的结构
- 核心渲染方法(组件输出方法):render
属性表达式
- 属性值要使用表达式,只要用 {} 替换 "" 即可
1、 输入(JSX)
const person = <Person name={window.isLoggedIn ? window.name : ''} />;
2、// 输出(JavaScript):
const person = React.createElement(
Person,
{name: window.isLoggedIn ? window.name : ''}
);
转义 解决办法
- 直接使用 UTF-8 字符
- 使用对应字符的 Unicode 编码查询编码
- 使用数组组装 <div>{['cc ', <span>©</span>, ' 2015']}</div>;
- 直接插入原始的 HTML
- 本身提供 dangerouslySetInnerHTML属性
<div dangerouslySetInnerHTML={{__html: 'cc © 2015'}} />
React 组件的构建方法
- React.createClass
- ES6 classes
- 无状态函数(stateless function)
1、React.createClass ( 0.14 版本发布)
const Button = React.createClass({
getDefaultProps() {
return {
color: 'blue',
text: 'Confirm',
};
},
render() {
const { color, text } = this.props;
return (
<button className={`btn btn-${color}`}>
<em>{text}</em>
</button>
);
}
});
2、ES6 classes
import React, { Component } from 'react';
class Button extends Component {
constructor(props) {
super(props);
}
static defaultProps = {
color: 'blue',
text: 'Confirm',
};
render() {
const { color, text } = this.props;
return (
<button className={`btn btn-${color}`}>
<em>{text}</em>
</button>
);
}
}
a、React 的所有组件都继承自顶层类 React.Component
b、声明了 props、context、refs等,原型上定义了 setState 和
forceUpdate 方法
3、无状态函数 ( 0.14 版本之后新增,官方颇为推崇)
function Button({ color = 'blue', text = 'Confirm' }) {
return (
<button className={`btn btn-${color}`}>
<em>{text}</em>
</button>
);
}
a、无状态组件只传入 props 和 context 两个参数
b、它不存在 state,也没有生命周期方法
React 数据流
- 数据是自顶向下单向流动的,即从父组件到子组件
- state 与 props,state 只关心每个组件自己内部的状态
- setState 是一个异步方法
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.state = {
count: 0,
};
}
handleClick(e) {
e.preventDefault();
this.setState({
count: this.state.count + 1,
});
}
render() {
return (
<div>
<p>{this.state.count}</p>
<a href="#" onClick={this.handleClick}>更新</a>
</div>
);
}
}
props
- React 用来让组件之间互相联系的一种机制
- className
- classPrefix
- onChange
与父组件通信
- this.props.onChange({activeIndex, prevIndex});
propTypes
- 类型检查,规范 props 的类型与必需的状态
- 不仅有基本类型,还包括枚举和自定义类型
- 函数类型的检查是 propTypes.func,而不是 propTypes.function。
- 对于布尔类型的检查是 propTypes.bool,而不是 propTypes.boolean。
这是因为 function 和boolean 在 JavaScript 里是关键词。
static propTypes = {
classPrefix: React.PropTypes.string,
className: React.PropTypes.string,
defaultActiveIndex: React.PropTypes.number,
activeIndex: React.PropTypes.number,
onChange: React.PropTypes.func,
children: React.PropTypes.oneOfType([
React.PropTypes.arrayOf(React.PropTypes.node),
React.PropTypes.node,
]),
};
生命周期
- 自然界和人类社会中各种客观事物的阶段性变化及其规律
- 当组件在挂载或卸载时;
- 当组件接收新的数据时,即组件更新时。
挂载:
-
componentWillMount (只会在组件初始化时运行一次)
-
componentDidMount (render执行之后、只会在组件初始化时运行一次)
卸载
- componentWillUnmount 这一个卸载前状态
- 会执行一些清理方法,如事件回收或是清除定时器。
更新
-
shouldComponentUpdate(nextProps, nextState) {
// return true;
} -
componentWillUpdate(nextProps, nextState) {
// ...
} -
componentDidUpdate(prevProps, prevState) {
// ...
}
如果组件自身的 state 更新了,那么会依次执行 shouldComponentUpdate、componentWillUpdate 、render 和 componentDidUpdate。
image.png image.png
网友评论