React组件&props
React编写组件主要是有两种方式:函数组件和class组件。一般声明组件的时候都会申明为首字母大写。
定义组件最简单的方式就是编写JavaScript函数:
1 | function Welcome(props) { |
还可以使用ES6的 class来定义组件:
1 | class Welcome extends React.Component { |
注意有一点:React是一个直接操作数据的声名式框架,它不会直接操作DOM,它是通过虚拟DOM来实现最后的渲染的,会帮我们节约掉大量操作DOM的代码。
子组件和父组件的通信方式
父组件想传递信息到子组件是利用props,state属性来实现
子组件想传递给父组件信息的话是通过调用父组件传递给子组件的方法间接的传递信息
子组件和父组件之间通信是单向数据流
这个也就是为什么组件无论是使用函数声明还是通过class声明,都决不能修改自身的props。因为这个属性是父组件传递给子组件的。这是为了保证当数据出现错误的时候能很容易的找到出错的地方在哪。
React虚拟DOM
在React中,render执行的结果得到的并不是真正的DOM节点,结果仅仅是轻量级的JavaScript对象,我们称之为virtual DOM。 虚拟DOM是React的一大亮点,具有batching(批处理)和高效的Diff算法。
这个批处理优化基于:setState是异步的,当多个变化很相近的时候就放到一起来去生成虚拟DOM。
它也是使得跨端应用得到实现的重要原因。
React修改数据之后的流程
state数据JSX模板- 数据+模板生成虚拟
DOM(损耗了性能):['div',{id: 'abc'},'hello world!'] - 用虚拟DOM的结构生成真实DOM来显示:
<div id='abc'>'hello world!'</div> state发生改变- 数据+模板生成新的虚拟
DOM - 比较原始虚拟
DOM和新的虚拟DOM的区别 - 直接操作
DOM,更改内容
JSX模板变成真实DOM的过程:JSX -> React.createElement -> js对象 -> 真实的DOM。
DIFF算法
两个树的完全的diff算法是一个时间复杂度为 O(n3)的问题。 但是在前端中,你会很少跨层地移动DOM元素,所以真实的DOM算法会对同一个层级的元素进行对比。

div只会和同一层级的div对比,第二层级的只会和第二层级对比。 这样算法复杂度就可以达到O(n).
利用深度优先遍历,记录差异然后把差异引用到真正的DOM树上。
React的生命周期函数
React的生命周期分为三个阶段:
- 挂载阶段
- 更新阶段
- 卸载阶段
constructor(组件构造函数)
如果没有显示定义它,我们会拥有一个默认的构造函数。在构造函数里面我们一般会做两件事:
- 初始化
state对象 - 给自定义方法绑定
this
render
React中最核心的方法,一个组件中必须要有这个方法
返回的类型有以下几种:
- 原生的
DOM,如div React组件Fragment(片段)Portals(插槽)- 字符串和数字,被渲染成
text节点 Boolean和null,不会渲染任何东西
componentDidMount
组件装载之后调用,此时我们可以获取到DOM节点并操作,,比如对canvas,svg的操作,服务器请求,订阅都可以写在这个里面,但是记得在componentWillUnmount中取消订阅
shouldComponentUpdate
函数原型shouldComponentUpdate(nextProps, nextState),有两个参数nextProps和nextState,表示新的属性和变化之后的state,返回一个布尔值,true表示会触发重新渲染,false表示不会触发重新渲染,默认返回true。
componentDidUpdate
组件改变之后调用,有三个参数prevProps,prevState,snapshot,表示之前的props,之前的state,和snapshot。第三个参数是getSnapshotBeforeUpdate返回的。在这个函数里我们可以操作DOM,和发起服务器请求,还可以setState,但是注意一定要用if语句控制,否则会导致无限循环
componentWillUnmount
当我们的组件被卸载或者销毁了就会调用,我们可以在这个函数里去清除一些定时器,取消网络请求,清理无效的DOM元素等垃圾清理工作
注意不要在这个函数里去调用setState,因为组件不会重新渲染了。
之前还有componentWillMount()和componentDidMount()是组件即将被渲染到页面之前触发和组件已经被渲染到页面中后触发,这个在现在的版本已经被去除了。使用HOOK能很方便的代替生命周期函数。