4

问题描述

代码如下

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

当首次加载页面时,会遍历data中所有的数据,每个数据都会判断一次isFavorite方法
但是如果data中push了新的对象,会从头渲染再重复判断一次isFavorite方法
我的项目中绑定的data量巨大,每次只要新增一小批内容,由于从头开始渲染,会导致cpu使用暴增。

问题出现的环境背景及自己尝试过哪些方法

尝试过
加:key 无效
加v-once 无效

相关代码

写了个demo完整代码如下

<!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">
        <span :class="isFavorite(i) ? 'red' : ''">{{d.name}}</span>
    </div>
</div>

<script src="https://cdn.bootcss.com/vue/2.5.22/vue.min.js"></script>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            data: [
                {
                    id: 1,
                    name: "one"
                },
                {
                    id: 2,
                    name: "two"
                },
                {
                    id: 3,
                    name: "three"
                }
            ],
            favorite: [
                {
                    id: 1,
                    name: "one"
                }
            ]
        },
        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>

你期待的结果是什么?实际看到的错误信息又是什么?

运行效果如下图,期望是不要重复渲染,只渲染新增部分。
实际测试发现只要v-for下有v-bind,就会出现从头开始重新渲染的问题

运行效果如下

zzzmh 105
2019-02-25 提问
4 个回答
3

已采纳

我来回答吧,你可以把会发生重复渲染的模板提取成子组件,就能够避免函数重复触发这样的问题了,下面是我优化后的代码,希望对你有所帮助

<!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: '#app',
    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>

这样就能保证只在新增的时候触发函数
clipboard.png

0

首先,感谢邀请。
1.个人感觉可能是vue的机制有关系,vue会监听绑定的数据,在数据变化时渲染dom,这个时候调用了isFavorite方法。
2.你可以尝试给数据添加个isFavorite属性默认false,如果添加对象的id等于this.favorite[0].id,就将isFavorite赋值为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)     
}

这样就只对新增的数据进行运算,方法的时间复杂度也降低了。
有个弊端就是只对新增数据运算的话,你的this.favorite就不能变化了。

0

加个key值,key值变化可以确定是否重新渲染

0

主要还是key的问题,如果重复渲染了说明key加的不对。

撰写答案

推广链接