vueWhy can’t we use index as the unique identifier? The following article will introduce to you the reasons why Vue cannot use index as the unique identifier. I hope it will be helpful to you!
This involves the DOM operation of native js and the optimization brought by virtual DOM. The following is divided into two parts to talk about
Let's first look at the way to natively operate dom nodes, but the browser's response to DOM operations is very energy-consuming, because changes in nodes will cause the browser to perform rearrangement and redraw operations (refer to Browser rendering page Process )
nbsp;html> <meta> <meta> <meta> <title>Document</title> <div> <ul></ul> </div> <script> let ul = document.querySelector('ul') for (let i = 0; i < 3; i++) { let li = document.createElement('li') li.innerHTML = i + 1 ul.appendChild(li) } </script>
In addition, many js codes dynamically change elements to cause the browser to rearrange, and the energy consumption can be imagined. If some nodes change , wouldn’t local rearrangement of those changed nodes save a lot of performance? ? ? The virtual dom introduced by vue uses this method. The following is a piece of vue code
nbsp;html> <meta> <meta> <meta> <script></script> <title>Document</title> <div> <ul> <item></item> </ul> <button>change</button> </div> <script> new Vue({ el: '#app', data() { return { list: [1, 2, 3] } }, methods: { change() { this.list.reverse() } }, components: { item: { props: ['num'], template: ` <div> {{num}} `, name: 'child' } } }) </script>
When the change button is clicked
If native js performs such an operation, it will inevitably be rearranged, but the page will only be partially changed, but Vue has greatly saved energy consumption after introducing virtual dom
In vue, you can get a virtual node tree before executing the rendering function, and you can use the virtual node tree to render the page. When the page dom node changes dynamically, before rendering, the newly generated virtual node will be compared with the last generated virtual node, and only the different parts will be rendered. Each virtual node is an object, describing the characteristics of a layer of containers. The following is the virtual node tree before clicking the change button in the vue code
vndoe = { tag: 'ul', children: [ { tag: 'li',key:0, children: [{ vnode: { text: '3' } }] }, { tag: 'li',key:1, children: [{ vnode: { text: '2' } }] }, { tag: 'li',key:2, children: [{ vnode: { text: '1' } }] } ] }复制代码
When change is clicked, a new virtual node tree will be generated and compared with it
After comparison, only the differences are rendered
So how to find the difference in the number of two virtual nodes? This involves the diff algorithm of vue source code
#After the life cycle is mounted, as long as the data source changes, the callback of the watcher observer will be triggered. Drive view updates
vm._update(v_rander())
_update will generate vnode to _patch_ to find different
_patch_ starts in the diff algorithm
key is the unique identifier in order to make the diff algorithm more efficient Accurately find the two nodes that need to be compared
We still use the previous code to look at it. In the diff algorithm , key is the unique identifier. When two virtual node trees are compared, the same key value will be found for comparison. If it is found that the key value is the same but the data inside is different, the diff algorithm will determine that it has changed and re-render it. In fact, they just changed their positions. When we add a unique identification id to it
nbsp;html> <meta> <meta> <meta> <script></script> <title>Document</title> <div> <ul> <item></item> </ul> <button>change</button> </div> <script> new Vue({ el: '#app', data() { return { list: [{ n: 1, id: 0 }, { n: 2, id: 1 }, { n: 3, id: 2 }, ] } }, methods: { change() { this.list.reverse() } }, components: { item: { props: ['num'], template: ` <div> {{num}} `, name: 'child' } } }) </script>复制代码
When the diff algorithm finds the same key value for comparison and finds that the key value is the same but the data inside is also the same, it will not re-render, but change their positions, which greatly saves the browser consumption, so use Using index as key will cause the optimization in diff to fail (reducing reusability and violating the original intention of virtual Dom)
nbsp;html> <meta> <meta> <meta> <script></script> <title>Document</title> <div> <ul> <li> <item></item> </li> </ul> <button>del</button> </div> <script> new Vue({ el: '#app', data() { return { list: [1, 2, 3] } }, methods: { del() { this.list.splice(0, 1) } }, components: { item: { template: '<div>{{Math.random()}}' } } }) </script>复制代码
After clicking the delete button
We found that it actually deleted the last item, because after deleting the data, due to the characteristics of the array, the subscript index and key of the remaining data will be changed to -1, that is, the second, three data keys will be changed from 1, 2 becomes 0,1, the diff algorithm will think that the data content of key 0,1 has changed, and the content of key 3 has been deleted, so it will re-render the first and second data and delete the third data, but in fact we delete The first content, the second, and the third are key values that have changed. Vue will not deeply compare the text content of sub-components. It can only perceive that the outer layer of objects has changed. Use the key to compare. If the key is not unique, it will incorrectly operate the virtual DOM tree and render incorrectly
(Learning video sharing: web front-end development, Basic programming video)
The above is the detailed content of A brief analysis of the reasons why Vue cannot use index as the unique identifier. For more information, please follow other related articles on the PHP Chinese website!