我们所需要了解的三个原则:
- 划分组件边界的原则
- React组件的数据种类
- React组件的生命周期
01|易于维护组件的设计要素
- 保持简单原则,功能模块的单一性!
- 高内聚,低耦合
- 功能的联系紧密 组件独立性
- 模块的耦合度非常低 依赖关系的弱化
02|React中的数据(props)
分为props(Property)和state
- 对内用state
- 对外使用props
- 关于Props:
React组件的Props很像是HTML中的属性,其实不是的,props支持多种形式的类型 除了字符串,props可以是任何一种JS语言支持的数据类型! 除了字符串的时候,需要使用花括号{}把props的值包裹住!
父组件提供给子组件一个 回调函数 子组件恰当时机调用回调函数,传入对应的值,就可以反过来把信息传递给外部世界!
- 读取props的值:
-
给this.props赋值也是React.component构造函数的工作之一! 组件要定义自己的构造函数的话一定要使用super使用父类的构造函数!
-
ES6方法创造的组件并不会将组件自动给我们绑定this到当前的实例对象上!
- 我们手动bind 构造函数 或者说 {} 中!
- 使用箭头函数 {()=> operaction}
- functionname = ()=> operation
- 使用propTypes
对应的借助propTypes帮助我们做组件规范和约束
- 该组件支持什么props
- 每个props应该是什么样的格式?
- React通过propTypes来支持这些功能!
Tips:
-
开发中非常不错的一个功能! 但是用在生产环境中并不合适
- 多余的代码量!
- propTypes检查需要消耗额外的CPU计算资源!
- 对应的错误信息只有开发者才能够看懂!
- 对于产品使用者来讲 PropTypes意义并不大!
-
解决方案:
- 在开发之后上线,使用工具对齐propTypes去除操作!
- 可以使用 babel-react-optimize 插件 (产品发布的时候使用!)
02|React中的数据(state)
state在React中是一个JS对象!
- 读取和设置state
- this[state] 或者说使用 this.state使用state
- 设置state需要使用 setState(); 参数是对象或者回调函数!
porps和state比对:
- prop用于定义外部接口,state用于记录内部状态
- prop赋值在外部使用组件的时候,state赋值在组件内部
- 组件不应该修改porp的值,state存在的目的就是让组件改变的!
03|组件的生命周期
- 三个阶段:
- 装载过程 Mount 组件第一次在DOM树中渲染的过程
- 更新过程 Update 组件重新被渲染的过程
- 卸载过程 UnMount 组件从DOM中删除的过程
- 成员函数:
其实该图就把对应的一些阶段阐述的很明白了!
API参考指南:about React Component API
- constructor
- 初始化state (构造函数是初始化state最理想的方式)
- 绑定成员函数的this环境! (成员函数在执行时候的this并不是和类实例自动绑定的! 在构造函数中this既是当前组件的实例!)
this.onClickIncrementButton = this.onClickIncrementButton.bind(this);
//以下的代码也能够实现同样的功能! ::称之为bind操作符!(来自babel)
this.foo = ::this.foo //===> this.foo = this.foo.bind(this);
-
React.createClass(ES6定义的组件组件之外的另一种方法 被官方逐渐废弃)
- getInitialState 返回值用来初始化组件的this.state
- getDefaultProps 返回值作为props的初始值!
-
render
- render函数并不做实际的渲染动作,返回JSX的描述,最终由React操作渲染过程
- 不渲染内容的情况下 可以返回 false或者null 不会渲染任何DOM元素!
- 作为纯函数单独存在!
对应的componentWillMount(组件更新前调用)和componentDidMount(所有的组件更新完毕之后调用!)
为什么是这样的呢?
render函数并不是渲染或者装载内容,只是JSX表示的对象,之后由React负责渲染,React把所有的组件返回的结果综合起来,才能知道如何产生DOM的修改! 等对应的组件render之后,才可能完成装载,之后才会调用各个组件的componentDidMount函数作为装载函数的扫尾工作!
- componentWillMount 适用于浏览器/服务器端
- componentDidMount 只适用于浏览器端
其实很好理解,Mount也就是所谓的挂载只能够挂载到DOM树上面,服务器端没有对应的DOM! 服务器端渲染并不会产生DOM树,通过React组件产生的只是一个纯粹的字符串!
有什么意义?
- 我们更好地理解render和render前后的流程,便于将对应的场景应该使用到合适的生命周期函数中!
- 便于将 第三方库与React更好的结合使用!
更新阶段
- componentWillReceiveProps(nextProps) 父组件的render函数被调用render函数里面被渲染的子组件就会经历更新过程,不管父组件传给子组件的props有没有改变,都会触发子组件的 componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
import React,{Component} from "react";
class Example extends Component{
render(){
return (
<button onClick={()=>this.forceUpdate()}>
Click me to repaint!
</button>
);
}
}
export default Example;
使用forceUpdate进行重新渲染,绘制! 但是使用箭头函数的方式并不推荐!
- 虽然说非常简介,但是每次都会有一个新的匿名方法对象!
- 可能会引发 子组件不必要的重新渲染!
import React,{Component} from "react";
class ControlPanel extends Component{
componentWillReceiveProps(nextProps){
console.log('enter componentWillReceiveProps'+this.props.caption);
}
render(){
return (
<div>
<button onClick={()=>this.forceUpdate()}>
Click me to repaint!
</button>
</div>
);
}
}
export default ControlPanel;
对应的将要过期的方法:
合理使用shouldComponentUpdate帮助你更好的优化React的性能!
-
更加细粒度的控制该组件是否需要更新! 通过(nextProps,nextState)进行判断!
-
比渲染速度更快的就是 不渲染
对应的componentWillUpdate和componentDidUpdate把render夹在中间! 并且都支持 浏览器端和服务器端
卸载过程:
- componentWillUnmount:被卸载之前适合做 请理性的工作!
- 没有卸载完之后的 函数,因为卸载完就完了,没有 卸载完再做的事情!
04|组件向外传递数据
-
组件的props可以是任何JS对象,函数是一等功名,本身就是对象,因此函数可以作为对象通过props传递给子组件,并且调用函数进行数据的传递操作!
-
父组件中定义对应的函数,作为回调函数通过props传递给子组件,子组件的数据发生变化,便可以通过该函数的调用来通知父组件!
- React组件和porp的局限(state)
- 对应上面的例子出现了一个很大的问题: 每次子组件的状态在维护的同时,父组件对应的也有一个状态同时维护饿了子组件的状态,说白了就是状态的重复!
- 对应的问题就是,状态的一致性如何保证!
- 解决方法:
- 以一个组件的状态为基准!
- 将对应的状态抽离出来,抽离到React之外的一个地方! 作为全局状态 各个组件保持与全局状态的一致就比较容易了!
全局状态就是唯一的可靠数据源! (Flux架构设计的概念)
- React组件和prop的局限(prop)
- 多层的组件结构,只能通过prop传递,过于麻烦,如果对应的prop过多的话,数据的传递对于用不到该prop中间层组件来讲太过于鸡肋!
- 不必要的prop通过层层传递,违反了设计理念低耦合!
网友评论