1、虚拟DOM
react效率极高,它可以创建存放组件的虚拟DOM,这一特点为开发人员提供了高度灵活性和惊人的性能收益
因为React能够提前计算出DOM中有哪些内容需要更改,并对dom做出相应的更新,通过这种方式,避免了及其消耗性能的DOM 从而大幅度提高工作效率
react如何创建虚拟dom?
答:React会在内存中创建并维护一个虚拟DOM树,当数据变化时,react会自动更新虚拟dom,然后将新的虚拟dom和旧的虚拟dom进行对比,
找到变化的部分,得出一个diff,然后将diff放到一个队列里,最终批量更新这些diff,并通过render函数将更改后的虚拟dom渲染到真实的dom上。
diff算法如何进行对比?
答:即:给定任意两棵树 找到最少的转换步骤
Facebook工程师算法:
1、两个相同组件产生类似的DOM结构,不同的组件产生不同的DOM结构
2、对于同一层次的一组子节点 他们可以通过唯一的id进行区分
不同节点类型比较的时候 需要删除原先的节点 并插入一个新的节点
相同类型节点比较的时候 react会对节点属性重设 从而实现节点的转换
逐层进行节点的比较 这样只需要对树进行一次遍历 就能完成整个DOM树的比较
列表节点的比较 需要有唯一的标识 如果没有唯一的标识 react会逐个对节点进行更新
这样的话更新过程会很慢而且浪费性能 如果用key唯一标识一个节点的话可以帮助react定位到正确的节点进行比较
从而大幅减少DOM操作次数 提高性能
2.单项数据流
其实reactjs的核心内容就是数据绑定,所谓数据绑定指的是只要将一些服务端的数据和前端页面绑定好,开发者只关注实现业务就行了
单向数据流:只要服务端数据发生变动,前端数据也变动
3. 组件化开发
React的组件化开发是体现其高效率的地方
组件其实就是html,js,css,image等部分的聚合体,页面结构中独立的功能部分
组件应该拥有的性质:
(1)可组合(Composeable):一个组件易于和其它组件一起使用,或者嵌套在另一个组件内部。如果一个组件内部创建了另一个组件,那么说父组件拥有(own)它创建的子组件,通过这个特性,一个复杂的UI可以拆分成多个简单的UI组件;
(2)可重用(Reusable):每个组件都是具有独立功能的,它可以被使用在多个UI场景;
(3)可维护(Maintainable):每个小的组件仅仅包含自身的逻辑,更容易被理解和维护
(4)可测试(Testable):因为每个组件都是独立的,那么对于各个组件分别测试显然要比对于整个UI进行测试容易的多。
划分组件的原则: 复用率高的,逻辑较为独立的
4.React组件的props和state
R数据的挂载主要依靠props和state;
1.属性(props)在组件外部传入,或者内部设置,组件内部通过this.props获得
2.状态(state)在组件内部设置或者更改,组件内部通过this.state获得
相似点:都是纯js对象,都会触发render更新,都具有确定性(状态/属性相同,结果相同)
不同点:属性能从父组件获取,状态不能
属性可以由父组件修改,状态不能
属性能在内部设置默认值 ,状态也可以
属性不在组件内部修改 ,状态要改
属性能设置子组件初始值 ,状态不可以
属性可以修改子组件的值,状态不可以
状态只和自己相关,由自己维护
属性不要自己修改,可以从父组件获取,也可以给子组件设置
组件在运行时自己需要修改的数据其实就是状态而已
5.ref
组件可以在renderdom结构中通过ref对dom、子组件进行标记
在组件里通过this.refs来获取,就可以操作真实DOM和调用子组件的属性方法
6.组件通信
(1)父 => 子 props
父:<MySecond name={'abc'} />
子:var message = this.props.name;
若需要验证传过来数据的类型 => PropTypes属性
npm i propTypes -S
import PropTypes from 'prop-types';
propTypes: {
name: React.PropTypes.string.isRequired,
}
其中propTypes类型有:
array
bool
func
number
object
string
none
element
为什么要验证?为了提高程序的健壮性 通用性,如果我期望的是数组,而传过来的是字符串 ,那就会导致出错
(2) 子 => 父
在父组件中给子组件绑定一个方法,然后在定义一个回调函数来接收子组件传过来的数据,
在子组件中通过this.props获得该方法,并传值,父组件接收到并处理
父:
changeBootPage(msg) {
this.setState({
bootPage: msg
});
}
<Start changeBootPage={this.changeBootPage.bind(this)}/>
子:
this.props.changeBootPage('none')
(3)兄弟组件:
通过父组件简洁通信 或者flux 、 redux状态管理工具,实现多个组件间的数据共享