Push in json in Vue v-for will cause the problem of methods rendering from scratch in v-bind.

problem description

the code is as follows

   

Jul.12,2022

Let me answer. You can extract the template that will be repeatedly rendered into subcomponents, so that you can avoid the problem of function triggering repeatedly. Here is my optimized code. I hope it will be helpful to you

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue2 test</title>
    <style>
        .red{
            color: red;
        }
    </style>
</head>
<body>
<div id="app">
    <button @click="loadMore">loadMore</button>
    <div v-for="(d, i) in data">
        <item :name="d.name" :id="d.id" :favorite="favorite" :key="i"></item>
    </div>
</div>

<script src="https://cdn.bootcss.com/vue/2.5.22/vue.min.js"></script>
<script>

  Vue.component('item', {
    props: ['name', 'id', 'favorite'],
    computed: {
      isFavorite: function () {
        console.log(this.id)
        for (let f of this.favorite) {
          if(this.id == f.id)
            return true
        }
        return false;
      }
    },
    template: `<span :class="isFavorite ? 'red' : ''">{{name}}</span>`
  })


  let vm = new Vue({
    el: '-sharpapp',
    data: {
      data: [
        {
          id: 1,
          name: "one"
        },
        {
          id: 2,
          name: "two"
        },
        {
          id: 3,
          name: "three"
        }
      ],
      favorite: [
        {
          id: 1,
          name: "one"
        },
        {
          id: 2,
          name: "two"
        }
      ]
    },
    methods: {
      // isFavorite: function (index) {
      //   console.log(index)
      //   for (let f of this.favorite) {
      //     if(this.data[index].id == f.id)
      //       return true
      //   }
      //   return false;
      // },
      loadMore: function () {
        this.data.push(
          {
            id:100,
            name:"100"
          }
        )
      }
    }
  });
</script>
</body>
</html>

this ensures that the function is triggered only when it is added
clipboard.png


first of all, thanks for the invitation.
1. Personally, it may have something to do with the mechanism of vue. Vue listens on the bound data and renders dom when the data changes. At this time, the isFavorite method is called.
2. You can try to add an isFavorite attribute to the data by default false, and if the id of the added object is equal to this.favorite [0] .id, assign isFavorite to true.

<div v-for="(d,i) in data">
    <span :class="d.isFavorite ? 'red' : ''">{{d.name}}</span>
</div>

loadMore: function () {
    var obj = {
        id:100,
        name:"100",
        isFavorite:false
    }
    if(obj.id == this.favorite[0].id){
        obj.isFavorite:false = true
    }
    this.data.push(obj)     
}

in this way, only the newly added data is calculated, and the time complexity of the method is reduced. The downside of
is that if you only operate on the new data, your this.favorite can't be changed.


add a key value, and the key value changes to determine whether to re-render


is mainly the problem of key. If you render repeatedly, the key is added incorrectly.

MySQL Query : SELECT * FROM `codeshelper`.`v9_news` WHERE status=99 AND catid='6' ORDER BY rand() LIMIT 5
MySQL Error : Disk full (/tmp/#sql-temptable-64f5-1befa47-31c80.MAI); waiting for someone to free some space... (errno: 28 "No space left on device")
MySQL Errno : 1021
Message : Disk full (/tmp/#sql-temptable-64f5-1befa47-31c80.MAI); waiting for someone to free some space... (errno: 28 "No space left on device")
Need Help?