触发render条件
1.组件mount
React组件构建并将DOM元素插入页面的过程称为挂载。当组件首次渲染的时候会调用render,这个过程不可避免。
2.setState方法被调用(组件或父组件中)
通常情况下执行setState会触发 render。
执行setState的时候一定会重新渲染吗?不一定,当setState传入null的时候,不会触发render;如果setState的参数不变,即判断state并未发生改变,也不会重新渲染。
3.父组件重新渲染
原则:只要一个节点变了,那么从它开始回溯的父节点全都是变的
react父节点数据变了,但传给子节点的没变,子节点变不变?只要父组件重新渲染了,即使传入子组件的props未发生变化,子组件也会重新渲染进而触发render。
如何在数据不变的情况下阻止子节点render?shouldComponentUpdate/pure component/memo
4.调用forceUpdate
渲染详细过程:
1.调用React.createElement()编译成虚拟v-DOM节点
2.diff
3.调用ReactDOMComponent(vdom).mountComponent()将虚拟DOM变成真实的DOM
4.调用appendChild(domNode)插入DOM树,显示出来
更新视图的过程(diff、patch)
Rendering
Batching
Whenever you call setState on a component, React will mark it as dirty. At the end of the event loop, React looks at all the dirty components and re-renders them.
This batching means that during an event loop, there is exactly one time when the DOM is being updated. This property is key to building a performant app and yet is extremely difficult to obtain using commonly written JavaScript. In a React application, you get it by default.
Sub-tree Rendering
When setState is called, the component rebuilds the virtual DOM for its children. If you call setState on the root element, then the entire React app is re-rendered. All the components, even if they didn’t change, will have their render method called. This may sound scary and inefficient but in practice, this works fine because we’re not touching the actual DOM.
First of all, we are talking about displaying the user interface. Because screen space is limited, you’re usually displaying on the orders of hundreds to thousands of elements at a time. JavaScript has gotten fast enough business logic for the whole interface is manageable.
Another important point is that when writing React code, you usually don’t call setState on the root node every time something changes. You call it on the component that received the change event or couple of components above. You very rarely go all the way to the top. This means that changes are localized to where the user interacts.
性能和渲染(Render)正相关
React的处理render的基本思维模式是每次一有变动就会去重新渲染整个应用。在Virtual DOM没有出现之前,最简单的方法就是直接调用innerHTML。
当DOM树很大时,遍历两棵树进行各种比对还是相当耗性能的,特别是在顶层setState一个微小的修改,默认会去遍历整棵树,这个过程会损耗性能。
VirtualDOM厉害的地方并不是说它比直接操作DOM快,而是说不管数据怎么变,都会尽量以最小的代价去更新DOM。React将render函数返回的虚拟DOM树与老的进行比较,从而确定DOM要不要更新、怎么更新。
基于虚拟DOM和高效Diff算法的完美配合,实现了对DOM最小粒度的更新。在个别复杂业务场景下,性能问题依然会困扰,此时需要采取一些措施来提升运行性能,很重要的一个方向就是避免不必要的渲染。
优化Render
当子组件过多或者组件的层级嵌套过深时,反复重新渲染状态没有改变的组件,可能会增加渲染时间又会影响用户体验,此时就需要对render进行优化。不必要的render会带来性能问题,因此主要优化思路就是减少不必要的render。
Selective Sub-tree Rendering
Finally, you have the possibility to prevent some sub-trees to re-render. If you implement the following method on a component:
boolean shouldComponentUpdate(object nextProps, object nextState)
based on the previous and next props/state of the component, you can tell React that this component did not change and it is not necessary to re-render it. When properly implemented, this can give you huge performance improvements.
In order to be able to use it, you have to have to be able to compare JavaScript objects. There are many issues that raises such as should the comparison be shallow or deep; if it’s deep should we use immutable data structures or do deep copies.
And you want to keep in mind that this function is going to be called all the time, so you want to make sure that it takes less time to compute than heuristic than the time it would have taken to render the component, even if re-rendering was not strictly needed.
第一次进入到页面的时候,会在没数据的情况下有一次渲染;等fetch成功后会再一次进行渲染。怎么解决第一次进入页面没数据的情况下,页面渲染时不报错?
1.给定同fetch回来的数据格式一样的默认数据,数组使用空数组,对象则属性都需要存在,值为默认值或者空值。
2.思路是条件渲染,设置一个判断条件,条件值不同,渲染的组件不同。
constructor(){
this.state = {
isLoading = true,
data: []
}
}
render(){
return (
{
this.state.isLoading
? <Loading />
: <Content />
}
)
}
3. 使用? operator
一个模块中props,data中存在同名的变量,会渲染哪一个,为什么?
react结合immutable.js为什么能提高渲染效率