This time I will show you how to implement the diff algorithm in React. What are the precautions for implementing the diff algorithm in React? The following is a practical case, let's take a look.
Preface
In the previous article, we have implemented the component function of React. From a functional perspective, we have implemented React core functions. But our implementation has a big problem: every time it is updated, the entire application or the entire component is re-rendered,DOM operations are very expensive, and the performance loss is very large.
In order to reduce DOM updates, we need to find the parts that really changed before and after rendering, and only update this part of the DOM. The algorithm that compares changes and finds out the parts that need to be updated is called the diff algorithm.Comparison Strategy
After the previous two articles, we implemented a render method that can render virtual DOM into real DOM , we need to improve it now so that it no longer stupidly re-renders the entire DOM tree, but finds out the parts that really changed. Many React-like frameworks implement this part in different ways. Some frameworks will choose to save the last rendered virtual DOM, and then compare the changes before and after the virtual DOM to obtain a series of updated data, and then These updates are applied to the real DOM. But there are also some frameworks that choose to directly compare the virtual DOM and the real DOM, so that there is no need to save the last rendered virtual DOM and can be updated while comparing. This is also the method we choose. Whether it is DOM or virtual DOM, their structure is a tree. The time complexity of the algorithm that completely compares the changes between the two trees is O(n^3), but considering that we rarely cross levels Move the DOM, so we only need to compare changes at the same level.1 2 3 4 5 6 7 8 |
|
DOM nodes and components. .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Compare text nodes
First consider the simplest text node. If the current DOM is a text node, update the content directly, otherwise Just create a new text node and remove the original DOM.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Compare non-text DOM nodes
If vnode represents a non-text DOM node, then there are several situations: If the types of the real DOM and the virtual DOM are different, for example, the current real DOM is a p, and the value of the vnode tag is 'button', then the original p has no use value, and a new button element is created directly. , and move all the child nodes of p under button, and then use the replaceChild method to replace p with button.1 2 3 4 5 6 7 8 9 |
|
Compare attributes
In fact, the diff algorithm not only finds changes in node types, it also finds out the attributes and events of nodes Listen for changes. We separate the comparison attribute as a method:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Compare child nodes
The comparison of the node itself is completed, and the next step is to compare its child nodes.这里会面临一个问题,前面我们实现的不同diff方法,都是明确知道哪一个真实DOM和虚拟DOM对比,但是子节点是一个数组,它们可能改变了顺序,或者数量有所变化,我们很难确定要和虚拟DOM对比的是哪一个。
为了简化逻辑,我们可以让用户提供一些线索:给节点设一个key值,重新渲染时对比key值相同的节点。
1 2 3 4 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
|
对比组件
如果vnode是一个组件,我们也单独拿出来作为一个方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
下面是相关的工具方法的实现,和上一篇文章的实现相比,只需要修改renderComponent方法其中的一行。
1 2 3 4 5 6 7 |
|
完整diff实现看这个文件
渲染
现在我们实现了diff方法,我们尝试渲染上一篇文章中定义的Counter组件,来感受一下有无diff方法的不同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
不使用diff
使用上一篇文章的实现,从chrome的调试工具中可以看到,闪烁的部分是每次更新的部分,每次点击按钮,都会重新渲染整个组件。
使用diff
而实现了diff方法后,每次点击按钮,都只会重新渲染变化的部分。
后话
在这篇文章中我们实现了diff算法,通过它做到了每次只更新需要更新的部分,极大地减少了DOM操作。React实现远比这个要复杂,特别是在React 16之后还引入了Fiber架构,但是主要的思想是一致的。
实现diff算法可以说性能有了很大的提升,但是在别的地方仍然后很多改进的空间:每次调用setState后会立即调用renderComponent重新渲染组件,但现实情况是,我们可能会在极短的时间内多次调用setState。
假设我们在上文的Counter组件中写出了这种代码
1 2 3 4 5 |
|
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
The above is the detailed content of How to implement diff algorithm in React. For more information, please follow other related articles on the PHP Chinese website!