【Vue】Vue v-for中json中Push,会导致v-bind中methods从头渲染一遍的问题
问题描述
代码如下
<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,就会出现从头开始重新渲染的问题
回答
我来回答吧,你可以把会发生重复渲染的模板提取成子组件,就能够避免函数重复触发这样的问题了,下面是我优化后的代码,希望对你有所帮助
<!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>
这样就能保证只在新增的时候触发函数
首先,感谢邀请。
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就不能变化了。
加个key值,key值变化可以确定是否重新渲染
主要还是key的问题,如果重复渲染了说明key加的不对。
以上是 【Vue】Vue v-for中json中Push,会导致v-bind中methods从头渲染一遍的问题 的全部内容, 来源链接: utcz.com/a/72771.html