1. key的作用
首先v-for
在
列表渲染时
,我们可以用v-for
基于一个数组来渲染一个列表。v-for
指令需要使用item in arr
形式的特殊语法来进行渲染列表,arr
是源数据,
<ul id="example-1">
<li v-for="item in arr" :key="item.id">
{{ item.message }}
</li>
</ul>
当Vue正在使用v-for渲染元素列表的时候,它默认的是使用**就地更新**的策略。如果数据项的顺序被改变,Vue将不会移动DOM元素来匹配数据项的顺序,而是采用了就地更新每个元素,并且确保他们在每个索引的位置正确渲染。
这个默认的模式是高效的,但是只是适用于不依赖子组件状态来临时DOM的状态的列表渲染输出。
为了能够更高效的渲染页面,你需要为每项提供一个唯一的key
值。
这边提醒您,渲染时尽量提供id
作为key
值。
为什么?
我想到的是当数组发生删除,插入变化时,下标将会重组。因该是这样可见。
vue中为什么不建议你使用数组下标作为 key值呢_yunchong_zhao的博客-CSDN博客
key
值特殊的属性主要使用在Vue
的虚拟DOM
算法,在新旧node
对比时辨识VNodes
,如果不使用key
,Vue
会使用一种最大限度减少动态元素,并且尽可能的尝试就地复用,相同类型元素的算法,而使用key
值时,它会就与key
的变化重新排列元素顺序,并且会移出key
不存在的元素
vue中为什么不建议你使用数组下标作为 key值呢_yunchong_zhao的博客-CSDN博客
Vue中key值的作用_理小理...的博客-CSDN博客_vue中的key值的作用
key值的作用
在大多数情况下使用在循环语句中,从本质来有两点:
1、主要是用在vue的虚拟Dom算法,在新旧nodes对比时辨识VNodes,相当于唯一标识ID,
2、vue会尽可能的高效的渲染元素,通常恢复已有的元素而不是从头开始进行渲染,因此使用key值可以提高渲染效率,同理,改变某一个元素的key值会使该元素重新被渲染。
2.nextTick的实现原理
this.$nextTick(() => {
for (var i = 0; i < this.$refs.tree.store._getAllNodes().length; i++) {
undefined
this.$refs.tree.store._getAllNodes()[i].expanded = false
}
})
nextTick作用:在下次DOM更新循环结束之后执行的延迟回调
1.vue是异步渲染,$nextTick会待Dom渲染完之后调用
2.页面渲染时会将data的修改做整合,多次data修改只会渲染一次
2.汇总data的修改,一次性更新试图
3.减少DOM操作次数,提高性能
首先nextTick并不是浏览器本身提供的一个异步API,而是Vue中,用过由浏览器本身提供的原生异步API封装而成的一个异步封装方法。
它对于浏览器异步API的选用规则如下,Promise存在取由Promise.then,不存在Promise则取MutationObserver,MutationObserver不存在setImmediate,setImmediate不存在最后取setTimeout来实现。
nextTick即有可能是微任务,也有可能是宏任务,从优先去Promise和MutationObserver可以看出nextTick优先微任务,其次是setImmediate和setTimeout宏任务。
同步代码执行完毕之后,优先执行微任务,其次才会执行宏任务
setTimeout(() => {
console.log("settimeout 1");
}, 0);
console.log("同步 1");
Promise.resolve().then(() => {
console.log("promise 1");
});
this.$nextTick(() => {
console.log("nexttick");
});
Promise.resolve().then(() => {
console.log("promise 2");
});
console.log("同步 2");
setTimeout(() => {
console.log("settimeout 2");
}, 0);
实现一个nextTick
public myNextTick(callback: Function) {
return Promise.resolve().then(() => {
callback();
});
3.Vue 响应式原理
Observer : 它的作用是给对象的属性添加 getter 和 setter,用于依赖收集和派发更新
用于收集当前响应式对象的依赖关系,每个响应式对象包括子对象都拥有一个 Dep 实例(里面 subs 是 Watcher 实例数组),当数据有变更时,会通过 dep.notify()通知各个 watcher。
Watcher : 观察者对象 , 实例分为渲染 watcher (render watcher),计算属性 watcher (computed watcher),侦听器 watcher(user watcher)三种
Watcher 和 Dep 的关系
watcher 中实例化了 dep 并向 dep.subs 中添加了订阅者,dep 通过 notify 遍历了 dep.subs 通知每个 watcher 更新。
4.为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?
Object.defineProperty 本身有一定的监控到数组下标变化的能力,但是在 Vue 中,从性能/体验的性价比考虑,尤大大就弃用了这个特性(Vue 为什么不能检测数组变动 )。为了解决这个问题,经过 vue 内部处理后可以使用以下几种方法来监听数组
Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue 2.x 里,是通过 递归 + 遍历 data 对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象是才是更好的选择。
Proxy 可以劫持整个对象,并返回一个新的对象。Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。