-
什么是虚拟dom
用js来描述元素与元素之间的关系 [父子 兄弟]
目的:高效渲染 以及快速更新
高效渲染和快速更新的手段是diff算法
-
diff算法
-
Diff算法就是在虚拟DOM树从上至下进行同层比对,如果上层已经不同了,那么下面的DOM全部重新渲染。这样的好处是算法简单,减少比对次数,加快算法完成速度。
-
diff 算法是⼀种通过同层的树节点进⾏⽐较的⾼效算法
其有两个特点:
- ⽐较只会在同层级进⾏, 不会跨层级⽐较
- 在diff⽐较的过程中,循环从两边向中间⽐较
diff 算法在很多场景下都有应⽤,在 vue 中,作⽤于虚拟 dom 渲染成真实 dom 的新旧 VNode 节点 ⽐较
⼆、⽐较⽅式 diff 整体策略为:深度优先,同层⽐较
1. ⽐较只会在同层级进⾏, 不会跨层级比较
2. ⽐较的过程中,循环从两边向中间收拢
下⾯举个 vue 通过 diff 算法更新的例⼦:
新旧 VNode 节点如下图所示
第⼀次循环后,发现旧节点D与新节点D相同,直接复⽤旧节点D作为 diff 后的第⼀个真实节点,同时 旧节点 endIndex 移动到C,新节点的 startIndex 移动到了c
第⼆次循环后,同样是旧节点的末尾和新节点的开头(都是 C)相同,同理, diff 后创建了 C 的真实节点 插⼊到第⼀次创建的 B 节点后⾯。同时旧节点的 endIndex 移动到了 B,新节点的 startIndex 移动 到了E
第三次循环中,发现E没有找到,这时候只能直接创建新的真实节点 E,插⼊到第⼆次创建的 C 节点之 后。同时新节点的 startIndex 移动到了 A。旧节点的 startIndex 和 endIndex 都保持不动
第四次循环中,发现了新旧节点的开头(都是 A)相同,于是 diff 后创建了 A 的真实节点,插⼊到前⼀ 次创建的 E 节点后⾯。同时旧节点的 startIndex 移动到了 B,新节点的 startIndex 移动到了 B
第五次循环中,情形同第四次循环⼀样,因此 diff 后创建了 B 真实节点 插⼊到前⼀次创建的 A 节点 后⾯。同时旧节点的 startIndex 移动到了 C,新节点的 startIndex 移动到了 F
新节点的 startIndex 已经⼤于 endIndex 了,需要创建 newStartIdx 和 newEndIdx 之间的所有 节点,也就是节点F,直接创建 F 节点对应的真实节点放到 B 节点后⾯
三、原理分析 当数据发⽣改变时, set ⽅法会调⽤ Dep.notify 通知所有订阅者 Watcher ,订阅者就会调⽤ patch 给真实的 DOM 打补丁,更新相应的视图
插槽
-
什么是插槽
(在子组件中用<slot></slot>划出一块区域来显示父组件中的页面结构,显示的结构在父组件的子组件标签中设置就行)
-
插槽怎么显示数据
显示的结构在父组件的子组件标签中设置就行
-
插槽分为几种
默认插槽 具名插槽 作用域插槽
-
作用域插槽怎么用
-
在子组件<slot></slot>通过v-bind绑定一个属性,挂载变量
-
<slot name="content" v-bind:us="user"></slot>
在父组件中子组件标签上通过v-slot:插槽名=“变量”来接受数据
-
数组去重
1、 ES6-set
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,
undefined, null,null, NaN,NaN,'NaN', 0, 0, 'a', 'a',{},{}];
function arr_unique1(arr){
return [...new Set(arr)];
//或者
//return Array.from(new Set(arr));
}
arr_unique1(arr); // (13)[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]
Map去重
function arr_unique2(arr) {
let map = new Map();
let array = new Array(); // 数组用于返回结果
for (let i = 0; i < arr.length; i++) {
if(map .has(arr[i])) { // 如果有该key值
map .set(arr[i], true);
} else {
map .set(arr[i], false); // 如果没有该key值
array .push(arr[i]);
}
}
return array ;
}
console.log(arr_unique2(arr)); //(13) [1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]
filter+indexOf
function arr_unique5(arr){
return arr.filter((val,index,item)=>{
return item.indexOf(val) === index;
});
}
arr_unique5(arr); // (12) [1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]
数组排序
function MaoPaoSort(arr){
for(var i = 0;i<arr.length-1;i++) {
for(var j = 0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
//把大的数字放到后面
var str = arr[j];
arr[j] = arr[j+1];
arr[j+1] = str;
}
}
}
}
var arr = [3,5,1,2,7,8,4,5,3,4];
//console.log(arr);[3,5,1,2,7,8,4,5,3,4];
MaoPaoSort(arr);
//console.log(arr);[1, 2, 3, 3, 4, 4, 5, 5, 7, 8]
插队排序
function InsertSort(arr) {
let len = arr.length;
let preIndex, current;
for (let i = 1; i < len; i++) {
preIndex = i - 1;
current = arr[i];
while (preIndex >= 0 && current < arr[preIndex]) {
arr[preIndex + 1] = arr[preIndex];
preIndex--;
}
arr[preIndex + 1] = current;
}
return arr;
}
var arr = [3,5,7,1,4,56,12,78,25,0,9,8,42,37];
InsertSort(arr);