# fed-e-task-03-01 **Repository Path**: jane900/fed-e-task-03-01 ## Basic Information - **Project Name**: fed-e-task-03-01 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-02-01 - **Last Updated**: 2021-02-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README #### 简答题 ###### 1、当我们点击按钮的时候动态给 data 增加的成员是否是响应式数据,如果不是的话,如何把新增成员设置成响应式数据,它的内部原理是什么。 ``` let vm = new Vue({ el: '#el' data: { o: 'object', dog: {} }, method: { clickHandler () { // 该 name 属性是否是响应式的 this.dog.name = 'Trump' } } }) ``` 答: 不是响应式数据,当我们在使用**new Vue**的时候,创建的 **Observer** 对象中,已经将**new Vue**中传递过来的**options**中的**data**数据的所有属性转成了**getter/setter** ,此时往**data.dog**中再添加数据,是不会触发 **defineReactive** 的**set**操作的,也就是数据是无法转换成响应式的。 将data.dog变成响应式的方法: ``` this.$set(this.dog, 'name', 'Trump') ``` ###### 2、请简述 Diff 算法的执行过程 1. 调用**patch**方法,拿到新老**Vnode**, 然后对新老**Vnode**进行标记:**oldStartIdx**、**oldEndIdx**、**newStartIdx**、**newEndIdx** 2. 通过**while**循环新老的**Vnode**,分情况进行标记, 当新老**Vnode**的**StartIdx**大于**EndIdx** ​ 循环过程分为以下几种情况: * 第一种 当新老**VNode**的开始节点满足**sameVnode**时,调用**patchVnode**,同时新老**Vnode**的开始索引 +1 * 第二种 当新老**Vnode**的结束节点满足**sameVnode**时,调用**patchVnode**,同时新老**Vnode**的结束索引 -1 * 第三种 当老**Vnode**的开始节点与新的**Vnode**的结束节点满足**sameVnode**时,调用**patchVnode**,将**oldStartVnode**对应的**dom**移动到老的**Vnode**的最后面,老的**Vnode**的开始索引 + 1,新的**Vnode**的结束索引 -1 * 第四种 当老的**Vnode**的结束节点与新的**Vnode**的开始节点满足**sameVnode**时,调用**patchVnode**将**oldEndVnode**对应的**dom**移动到老的**Vnode**的最前面,老的**Vnode**的结束索引 - 1,新的**Vnode**的开始索引 +1 * 第五种 以上四种情况都不满足,则将新的**Vnode**中的开始节点与老的**Vnode**中的节点依次进行比较,如果满足**sameVnode**,则将在老的**Vnode**中找出的那个相同的节点移动到老的**Vnode**的最前面,如果一轮比较下来都不满足**sameVnode**,则创建一个新的节点,插入到老的**Vnode**的最前面 3. 循环结束后 循环结束后也分两种情况: * 第一种:老的**Vnode**的数量比新的**Vnode**的数量少 通过查找事先建立好的以旧的 **Vnode**为 **key** 值,对应 **index **序列为 **value **值的哈希表。从这个哈希表中找到与 新的**Vnode**的开始节点**key**一致的老的 VNode 节点,如果两者满足 **sameVnode **的条件,在进行 patchVnode 的同时会将在老的**Vnode**中查找出来的这个节点 移动到 老的**Vnode **对应的位置,如果不满足 **sameVnode **的条件,则说明是新的创建的节点,此时调用 **createElm** 创建一个新的 dom 节点移动到老的**Vnode **对应的位置。 * 第二种:老的**Vnode**的数量比**Vnode**的数量多 通过查找事先建立好的以旧的 **Vnode**为 **key** 值,对应 **index **序列为 **value **值的哈希表。从这个哈希表中找到与 新的**Vnode**的开始节点**key**一致的老的 VNode 节点,如果两者满足 **sameVnode **的条件,在进行 patchVnode 的同时会将在老的**Vnode**中查找出来的这个节点 移动到 老的**Vnode **对应的位置,如果不满足 **sameVnode **的条件,则说明这些节点需要删除,此时只需要删除对应的节点。