1.如果开发者使用JSX写react,那么babel会先将JSX编译为能被浏览器识别的JS语法。
(babel其实就是一个JavaScript编译器,可以解决浏览器兼容问题)
2.执行render函数,渲染虚拟DOM
3.根据虚拟DOM,渲染出真实DOM
4.如果页面更新,通过setState改变数据,告诉react去更新渲染
5.react就会自动调用render函数,重新渲染虚拟DOM
6.react根据diff算法对比最新虚拟DOM和以前的虚拟DOM有什么区别,然后渲染区别部分的真实DOM。
1.声明式设计
2.单向数据流
3.组件化
4.运用虚拟DOM和diff算法。
声明式设计:
声明式就是关注结果,不管机器是如何操作的。
react不操作修改DOM,只是声明了页面应该是什么样的,在react中只需要维护可变的数据state,通过setState改变数据,让react框架帮助完成相关DOM操作。
单向数据流:
单向数据流就是数据在某个节点被改变后,只会影响一个方向上的其他节点。
在react中单向数据流就是数据由外层组件向内层组件进行传递和更新,单向数据流保证数据的可控性。
1)为什么使用单向数据流?
因为react中父组件通过props传递数据给子组件,如果不是单向数据流,那么子组件修改props,导致父组件和其他关联组件受到影响,UI界面渲染更新,很容易造成混乱。而且react也做了处理避免发生这种情况,props是只读的不可更改。
2)但是react组件之间是可以实现相互通信的,组件之间通信的方法有哪些?
父组件向子组件通信:
就是上面提到的通过props。子组件用props访问数据.
子组件向父组件通信:
父组件将一个函数作为props传递给子组件,子组件访问调用函数传参,实现向父组件传递数据
兄弟组件通信:
使用父组件当作中间组件,a组件向父组件传递数据,再由父组件传递给b。这就变成了子组件向父组件传递,父组件向子组件传递数据的问题。
跨级组件通信:
使用context,context相当于一个全局变量,是一个大容器,把要通信的内容放进这个容器中。
父组件要声明自己支持context,并提供context中属性的propTypes
子组件需要声明自己需要使用 context,并提供其需要使用的 context 属性的 PropTypes.
父组件需提供一个 getChildContext 函数,以返回一个初始的 context 对象
注意:
如果在组件中使用constructor,则需要在constructor里传入参数context,并且在super调用中传入context,否则无法使用context。
还有context对象中的属性是只读的,不能修改,如果想要修改,可以使context里属性和state或props关联起来。
跳转组件间:
可以通过this.props.history.match.params访问数据.
组件化:
react中可以声明组件,组件的可重用性提高了开发效率。
运用虚拟DOM和diff算法:
虚拟DOM:
虚拟DOM本质就是一个JS对象,包含了tag、props、children属性,DOM是树形结构,使用js对象很容易可以模拟表示。
1)为什么要使用虚拟DOM?
节约成本,提高效率。操作js对象比操作DOM
的代价更小,也更快速。
而且用传统的原生api
或jQuery
去操作DOM
时,浏览器会从构建DOM
树开始从头到尾执行一遍流程。一次操作时,需要更新n个DOM
节点,收到第一个更新DOM
请求后会立马执行流程,这样会执行n次。而虚拟DOM不会立刻操作DOM,而是将这n词更新经过diff算法保存到js对象中,最终将这个js
对象一次性attach
到DOM
树上。
抽象了原本的渲染过程,实现了跨平台的能力。
diff算法:
react的diff算法:
1.react首先对新集合进行遍历,for( name in nextChildren)。
2.通过唯一key来判断老集合中是否存在相同的节点。如果没有的话创建,如果有的话,if (preChild === nextChild )会将节点在新集合中的位置和在老集合中lastIndex进行比较
3.如果if (child._mountIndex < lastIndex) 进行移动操作,否则不进行移动操作。
4.如果遍历的过程中,发现在新集合中没有,但在老集合中有的节点,会进行删除操作。
vue的diff算法:
1.旧children和新children各有两个头尾的变量StartIdx和EndIdx,头头、尾尾、头尾、尾头对比,一共有4种比较方式。
2.如果4种比较都没匹配,如果设置了key,就会用key进行比较,在比较的过程中,变量会往中间靠,一旦StartIdx>EndIdx表明旧children和新children至少有一个已经遍历完了,就会结束比较。
1)React 中 keys 的作用是什么
Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。
开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。
1.react只是mvc设计模式里面的v层,当数据发生变化了,不会渲染最新视图,必须内部调用setState进行更新;Vue则是MVVM模式,数据变化自动更新渲染视图。
2.state对象在react应用中不可变的,需要使用setState方法更新状态;在vue中,state对象不是必须的,数据由data属性在vue对象中管理。
3.数据绑定: vue实现了数据的双向绑定(v-model),react数据流动是单向的。
4.virtual DOM不一样,vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。而对于React而言,每当应用的状态被改变时,全部组件都会重新渲染,所以react中会需shouldComponentUpdate这个生命周期函数方法来进行控制。
1)关于设计模式MVC、MVP、MVVM
MVC:用户操作的时候,View 传送指令到 Controller,Controller 完成业务逻辑后,要求 Model 改变状态,Model 将新的数据发送到 View,用户得到反馈。
m:model 数据模型层 封装数据和数据处理方法
v:view 视图层
c:controller 控制器,c的作用是将m层的数据在v层上进行显示
MVP:
M、V、P之间双向通信。View 与 Model之间不通信,都通过 Presenter 传递,Presenter完全把Model和View进行了分离,主要的程序逻辑在Presenter。
MVVM:
mvvm就是为了解决mvc反馈不及时的问题,它实现了View和Model的自动同步,也就是当Model属性改变时,vm层可以感知数据的变化,然后实时的渲染最新的视图,并且这个是自动的操作。不用再自己手动操作,来改变View的显示,而是改变属性后该属性对应View层显示会自动改变。
2)关于shouldComponentUpdate防止重复渲染:
shouldComponentUpdate(nextProps, nextState),nextProps: 表示下一个props,nextState: 表示下一个state的值。
官方API解释道根据 shouldComponentUpdate() 的返回值,判断 React 组件的输出是否受当前 state 或 props 更改的影响。
当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。返回值默认为 true。首次渲染或使用 forceUpdate() 时不会调用该方法。