This is the first day of my participation in the First Challenge 2022

Hello everyone, I am a bowl week, a front end that does not want to be drunk (inrolled). If I am lucky enough to write an article that you like, I am very lucky

Writing in the front

When we use the V-for directive, You suggest that we add a unique attribute key to each item, as stated in the Vue documentation:

To give Vue a hint that it can keep track of the identity of each node to reuse and reorder existing elements, you need to provide a unique *key*attribute for each item, unless traversing the DOM content of the output is very simple.

See this, will have the following question:

  • Why add a unique onekey?
  • Why not recommend indexes as uniquekey?
  • Why not use random numbers as uniquekey?

Let’s answer each of these questions in turn.

What is the key

The key attribute is explained as follows:

  • keyAttribute is mainly used in the virtual DOM algorithm of Vue to identify VNodes when comparing old and new nodes.
  • If not usedkeyVue uses an algorithm to minimize element movement and tries to modify/reuse elements of the same type in place as much as possible;
  • While the use ofkeyIt will be based onkeyChanges to reorder elements and remove/destroy elements where the key does not exist.

After reading these contents, I became even more confused, and a new problem emerged:

  • What is a Vnode?
  • What is the virtual DOM?
  • There is nokeyWhen, how to try to modify and reuse?
  • There arekeyHow is the time based onkeyRewrite permutation?

Let’s move on.

Virtual DOM

VNode

First let’s take a look at vNodes. VNode is a Virtual Node, also known as a Virtual Node. In Vue, all components and elements are ultimately represented as vNodes. The essence of a VNode is actually a JavaScript object, such as the following Node:

<div class="name" style="font-size: 3rem; color: #333;">A bowl of weeks</div>
Copy the code

Its final VNode looks like this:

const vNode = {
  type: 'div'.props: {
    class: 'name'.style: {
      fontSize: '3rem'.color: '# 333',}},children: 'Bowl Week',}Copy the code

Virtual DOM

If there is not only one node, but many nodes, forming a VNode Tree, also known as the virtual DOM, as shown in the following figure:

This means that HTML code written in Vue is converted to the virtual DOM before it is rendered to the real DOM.

Virtual DOM VS real DOM

As we mentioned earlier, rendering the real DOM in Vue takes three steps, while native DOM only takes two steps, as shown below:

If you look at the diagram alone, it’s no surprise that the direct generation of the real DOM is faster.

In fact, if the content of a node changes, comparing the virtual DOM is better than directly comparing the real DOM, which is why frameworks like Vue and React use the virtual DOM.

The comparison mentioned above is the diff algorithm used.

Processing without using the key attribute

In packages\runtime-core\ SRC \renderer.ts, about 1600 lines indicate which functions are called with and without keys, as shown below:

Now let’s go directly to the patchUnkeyedChildren() method and see what we do in this method, as shown below:

If you don’t understand just by looking at the picture, let’s take an example, the code is as follows:

<body>
  <div id="app"></div>
  <template id="my-app">
    <ul class="list-group">
      <li class="list-group-item" v-for="item in list">{{item.name}}</li>
    </ul>
  </template>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    Vue.createApp({
      template: '#my-app'.data() {
        return {
          list: [{id: 0.name: 'HTML' },
            { id: 1.name: 'CSS' },
            { id: 2.name: 'JavaScript' },
            { id: 3.name: 'Vue.js' },
            { id: 4.name: 'React.js' },
          ],
        }
      },
    }).mount('#app')
  </script>
</body>
Copy the code

The running results are as follows:

Now we insert a {id: 5, name: ‘Ajax’} in front of vue.js, with the old and new virtual DOM as shown below:

The execution process is as follows:

If the old VDOM is more than the new VDOM, the excess parts are unloaded directly.

Processing using the key attribute

The handling of the key property is the focus of this article. Let’s first look at what the patchKeyedChildren() method does.

As we can see, this method is rather long, but it is divided into five steps, which we look at in turn:

Tips: The Vue framework developers all write comments, do you think you don’t need to write comments ????

Let’s take a look in turn. The first step is to traverse from the beginning. The main content is as follows:

Let’s take an example:

So we compare key 0, we find consistency, we continue to compare until we compare key 3 and key 5, we break out of this while loop.

The operation of the second step is basically the same as the first step, except that it starts from the tail, and the main content is as follows:

Example:

The third and fourth steps are to add new nodes or remove old nodes respectively. The main code is as follows:

Example:

The last step, the most complex exception, is used to handle intermediate out-of-order, or move new exceptions, as shown in the following example:

Therefore, it can be found that when Vue performs diff algorithm, it will try its best to use key to optimize operations, so the key attribute is necessary.

Why not use an index as a key

If we use index as the key, suppose we have the following array:

list: [
  {name: 'HTML'},
  {name: 'CSS'},
  {name: 'JS'},]Copy the code

Let’s add an item at the top:

list.unshift({name: 'Bowl Week'})
Copy the code

If an index is used as a key, the following problems occur:

So we try to use a unique and unchanging value for the key.

Note: Do not use a random number as the **key****, or each comparison will be different **.

Write in the last

That’s the end of this article, if there are mistakes, welcome correction; If it helps you, please give me a thumbs-up. After all, drawing is not easy