最近用vue做一个小东西,发现了一个奇怪的现象,当模板使用数组进行v-if判断时,如果修改数组的值,页面渲染会明显有延迟,示例代码如下:
<template>
<div class="moudle" v-for="v in list" :key="v.id">
<div class="btn" @click="show_more(v.id)"></div>
<div class="more" v-if="more[v.id]">这个更多显示反应有延迟</div>
<div class="content">{{v.name}}</div>
</div>
</template>
<script>
export default {
data() {
return {
list:[{'id':0,'name':'a'},{'id':1,'name':'b'},{'id':2,'name':'c'}],
more: [false,false,false]
}
},
methods: {
show_more(id) {
this.more[id] = true; //此处代码执行完毕约1s后页面才有反应
console.log('set done!');
}
},
}
</script>
可以看到,代码逻辑非常简单,通过console.log日志能看到点击瞬间就执行完毕了,但是延迟将近1s后more区域才显示,把v-if换成v-show没有变化,把more变量改为非数组变量就能正常瞬间显示。
经过反复测试,发现vue的虚拟dom渲染在数组组件更新的地方代码逻辑为:
vue/src/core/observer/index.js data数据会统一转为Observer类,之后的this.数组的修改会触发dependArray()函数遍历数组进行递归的ob转换和监听绑定。
解决方法一(推荐):用$set直接修改单个值,不会触发整个数组组件更新,又能响应式
show_more(id) {
//this.more[id] = true;
this.$set(this.more, id, true); //不会触发组件更新
}
解决方法二:用cost []的方式定义数据,在初次调用时慢,初始化以后就快了
<script>
const more = [false,false,false];
export default {
data() {
return {
list:[{'id':0,'name':'a'},{'id':1,'name':'b'},{'id':2,'name':'c'}],
more: more
}
},
methods: {
show_more(id) {
this.more[id] = true;
console.log('set done!');
}
},
}
</script>
yan 20.1.10
参考:https://juejin.im/post/5c0dec8be51d451dac076f76
