preface

Today, a friend of mine asked me a problem he encountered. When he dynamically added the array operation, there would be a rendering disorder. The num displayed on the page and in the array were inconsistent, which caused the problem in the demo. The following image is rendered as 3 and 3 instead of 2 and 3. (PS: there is no discussion of the method of addition and subtracting. Here he directly changed the tripIndex, so this can’t be used as the key value.

Attach code (just a simple vue2 with a reference to Element-UI)

<template> <div class="con"> <div><el-button size='mini' @click='clickEvent'> Test </el-button></el-button></div> <div style="width:1000px; padding:50px"> <el-table :data="tableData" border style="width: 100%" v-if='isShow'> <el-table-column v-for="(item, index) in tableHeader" :key='item.id' :prop="item.data" width="100" align="center" > <template slot="header" slot-scope="scope"> <div> <i @click="addHeade(item.tripIndex)" class=" myIcon operateLine-item" >+</i> <i @click="subHeade(item.tripIndex)" class=" myIcon" >-</i> </div> {{ `${item.tripIndex} ${getMain(item)} ` }} </template> </el-table-column> </el-table> </div> </div> </template> <script> export default { name: "TestPage", components: {}, data() { return { isShow:true, tableHeader: [ { tripIndex: 1, data: "data", id:1 }, { tripIndex: 2, data: "data", id:2 }, { tripIndex: 3, data: "data", id:'3' }, { tripIndex: 4, data: "data", id:'4' }, { tripIndex: 5, data: "data", id:'5' } ], tableData: [ { data: "1" } ] }; }, mounted() {}, methods: {clickEvent(){console.log(this.tableheader)}, getMain(v) {if (v.ripIndex % 2 == 0) {return "sub "; } else {return "master "; } }, addHeade(v) { this.tableHeader.forEach(element => { if (element.tripIndex > v) { element.tripIndex += 1; }}); this.$nextTick(() => { console.log(this.tableHeader); }); console.log(this.tableHeader); let addItem = { tripIndex: v + 1, data: "data", }; console.log(v); this.tableHeader.splice(v, 0, addItem); }, subHeade(v) { this.tableHeader.splice(v - 1, 1); this.tableHeader.forEach(element => { if (element.tripIndex > v) { element.tripIndex -= 1; }}); } }, created() {} }; </script> <style scoped> .con { overflow: auto; position: relative; width: 100%; height: 100%; } .operateLine-item { margin-right: 10px; } .myIcon { color: #1890ff; cursor: pointer; } </style>Copy the code

To solve

In fact, I have encountered similar problems so I gave three solutions directly at that time

  1. This.$forceUpdata() forces a refresh.
  2. Use v-if to force a refresh

3. Add a unique id and specify the ID as the key after v-for

:key='item.id'
...
    let addItem = {
        tripIndex: v + 1,
        data: "data",
        id: new Date().getTime()
      };
      
Copy the code

The last two of these three methods are feasible using forced refresh to re-render. There’s a solution for a successful demo, but I don’t really know what it is so I’m going to have to think about it

Analysis of the

That was my judgment at the time

Since do not understand this time to start baidu, here attached a very interesting zhihu similar question and answer such as here there are similar questions

Reproduce the Demo connectionAdd the next two clicks three times and then delete the first one and you will have similar rendering problems

Search vUE official website documents have a sentence is very interesting

When Vue is updating a list of elements rendered using V-for, it defaults to the "update in place" policy. If the order of data items is changed, Vue does not move DOM elements to match the order of data items, but instead updates each element in place and ensures that they are rendered correctly at each index location. Vue 1.x track-by="$index"Copy the code

The term “update in place” strategy may bring us closer to the answer, update in place.

Related to the answer

I think I need to simulate the AST abstract tree to print out the corresponding results (I’ll track it later)

summary

My own conclusion: The problem caused by the diff algorithm, and the existence of the key value is to better diff out the AST abstract tree, when there is no key value will use the strategy of in-place update, if the key value confusion will also appear rendering problems.

Big guys if have understand and just see this article, but also hope not stingy to give advice!