React 组件
传统方法(JavaScript)的规范标准组件信息
- 基本的封装性。
- 简单的生命周期呈现。
- 明确的数据流动。
Web Components 的组成成分
1. HTML Templates 定义了之前模板的概念
2. Custom Elements 定义了组件的展现形式
3. Shadow DOM定义了组件的作用域范围、可以囊括样 式
4. HTML Imports 提出了新的引入方式。
React 组件的构建
React 组件基本上由组件的构建方式、组件内的属性状态与生命周期方法组成。
React 组件可以接收参数,也可能有自身状态。一旦接收到的参数或自身状态有所改变, React 组件就会执行相应的生命周期方法,最后渲染。
React 与 Web Components 的不同
- React 自定义元素是库自己构建的
- React 渲染过程包含了模板的概念(JSX)
- React 组件的实现均在方法与类中,因此可以做到相互隔离,但不包括样式
- React 引用方式遵循 ES6 module 标准
React组件构建的三种官方方式
- React.createClass( 最传统、也是兼容性最好)
示例:
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>
);
}
});
构建新的组件对象。
当另一个组件需要调用 Button 组件时,只用写成 <Button />
,就可以被解析成 React.createElement(Button) 方法来创建 Button
- 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>
);
}
}
从调用内部方法变成了用类来实现
说明:React 的所有组件都继承自顶层类 React.Component。它的定义非常简洁,只是初始化了 React.Component 方法,声明了 props、context、refs 等,并在原型上定义了 setState 和 forceUpdate 方法。内部初始化的生命周期方法与 createClass 方式使用的是同一个方法 创建的。
- 无状态 函数(stateless function)
function Button({ color = 'blue', text = 'Confirm' }) {
return (
<button className={`btn btn-${color}`}>
<em>{text}</em>
</button>
);
}
无状态组件只传入 props 和 context 两个参数;也就是说,它不存在 state,也没有生命周期方法,组件本身即上面两种 React 组件构建方法中的 render 方法。
优点:创建时始终保持了一个实例,避免了不必要的检查和内存分配,做到了内部优化
React数据流
数据是自顶向下单向流动的,从父组件到子组件。
- state
自身管理组件的内部状态
当使用了setState时,组件重新渲染
注意:setState——异步操作
例:计数器
import React, { Component } from 'react';
class Products 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>
);
}
}
export default Products;
在这里我们就定义了一个state——count
点击“更新”,数字+1
props
组件之间 互相联系的一种机制,通俗地说就像方法的参数一样
组件的props一般包含:
①. className:根节点的 class
②. classPrefix:class 前缀
③. defaultActiveIndex 和 activeIndex:默认的激活索引
④. onChange:回调函数- 子组件prop
1) 通过React.Children.map 方法遍历子组件
2)React.cloneElement( element, [props], [...children] )
方法克隆到子组件中
3) 最后返回
这种子组件的返回方式叫做动态子组件
- 子组件prop
例:
getTabPanes() {
const { classPrefix, activeIndex, panels, isActive } = this.props;
return React.Children.map(panels, (child) => {
if (!child) { return; }
const order = parseInt(child.props.order, 10);
const isActive = activeIndex === order;
return React.cloneElement(child, {
classPrefix,
isActive,
children: child.props.children,
key: `tabpane-${order}`,
});
});
}
调用方法:
render() {
return (<div>{this.getTabPanes()}</div>);
}
2. 组件props
1)对于子组件而言,我们不仅可以直接使用 this.props. children 定义,也可以将子组件以 props 的形式传递
2)可以加入更多的自定义元素,可以是多行的,甚至可以插入动态数据。
例:
getTabs() {
const { classPrefix, activeIndex, panels } = this.props;
return React.Children.map(panels, (child) => {
if (!child) { return; }
const order = parseInt(child.props.order, 10);
let classes = classnames({
[`${classPrefix}-tab`]: true,
[`${classPrefix}-active`]: activeIndex === order,
[`${classPrefix}-disabled`]: child.props.disabled,
});
return (<li>{child.props.tab}</li>);
});
}
3. function prop 与父组件通信
1) 对于 state 来说,通信集中在组件内部
2) 对于 props 来说,通信是父组 件向子组件的传播
相关代码:
handleTabClick(activeIndex) {
// ...
this.props.onChange({ activeIndex, prevIndex });
}
点击事件 handleTabClick 触发了 onChange prop 回调函数给父组件必要的值
4. propTypes
propTypes 用于规范 props 的类型与必需的状态。
1) 如果组件定义了propTypes,那么在开发环 境下,就会对组件的 props 值的类型作检查
2)如果传入的 props 不能与之匹配,React 将实时在控 制台里报 warning
3) 在生产环境下,这是不会进行检查的
例:
Tabs 组件的 propTypes
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,]),
};
TabPane 组件 的 propTypes
static propTypes = {
tab: React.PropTypes.oneOfType([
React.PropTypes.string, React.PropTypes.node,
]).isRequired,
order: React.PropTypes.string.isRequired,
disable: React.PropTypes.bool,
}