# fed-e-task-03-01 **Repository Path**: MinarLearningCenter/fed-e-task-03-01 ## Basic Information - **Project Name**: fed-e-task-03-01 - **Description**: No description available - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-11-15 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 简答题 ## 当我们点击按钮的时候动态给 data 增加的成员是否是响应式数据,如果不是的话,如何把新增成员设置成响应式数据,它的内部原理是什么。 ```javascript let vm = new Vue({ el: '#el' data: { o: 'object', dog: {} }, method: { clickHandler () { // 该 name 属性是否是响应式的 this.dog.name = 'Trump' } } }) ``` 此处是一段 Vue2.x 代码,该属性不是响应式的,因为 Vue2.x 的响应式原理是把 data 中的对象以及其子属性设置 getter、setter 来监听属性的修改,而不能监听属性的增加。故此处需要调用\$set 手动设置 getter、setter 来监听新属性: ```javascript let vm = new Vue({ el: '#el' data: { o: 'object', dog: {} }, method: { clickHandler () { // 该 name 属性是是响应式的! this.$set(this.dog, 'name', 'Trump') } } }) ``` ## 请简述 Diff 算法的执行过程 Diff 算法是将给定的两个节点数组先进行对比,从而找到它们的差异,然后对老节点的 dom 进行更新、增加、删除、移动操作,使得老节点与新节点一致。 更详细的说,Diff 算法是将新老节点数组先进行首尾对比,从而快速找到它们的差异,如果首尾对比失败,则再去遍历老节点的元素,找到相同节点,从而更新、移动老节点。最后,将新节点多出来的元素全部插入老节点未对比部分的末尾,再老节点未对比的元素全部删除。 以下是每个步骤的详细说明“ ### 首尾节点对比 对比节点时,会从新老节点的首尾两端分别进行两两比较,直到对比完新节点或者老节点的全部元素。由于是双向对比,所以新老节点都各有开始、结束共 4 个索引。 #### 老节点开头与新节点开头对比 将老节点的第一个元素与新节点的第一个元素开始对比,如果是同一个元素,则将新元素更新到老元素上,并且新老元素的开始索引+1,本轮对比结束。下一轮就会将老节点的第二个元素对比新节点的第二个元素,依此类推。如果对比的两个元素不是同一个元素,则进行下一个条件的对比。 #### 老节点结尾与新节点结尾对比 将老节点的最后一个元素与新节点的最后一个元素开始对比,如果是同一个元素,则将新元素更新到老元素上,并且新老元素的结束索引-1,本轮对比结束。下一轮就会将老节点的倒数第二个元素对比新节点的倒数第二个元素,依此类推。如果对比的两个元素不是同一个元素,则进行下一个条件的对比。 #### 老节点开头与新节点结尾对比 将老节点的第一个元素与新节点的最后一个元素开始对比,如果是同一个元素,则将新元素更新到老元素上。由于此节点已经是新节点的最后一个节点,所以此时应该操作 dom,把该节点移动到老节点的末尾以保持顺序一致,并且老元素的开始索引+1,新元素的结束索引-1,本轮对比结束。下一轮继续将老节点的第二个元素对比新节点的倒数第二个元素,依此类推。如果对比的两个元素不是同一个元素,则进行下一个条件的对比。 #### 老节点结尾与新节点开头对比 将老节点的最后一个元素与新节点的第一个元素开始对比,如果是同一个元素,则将新元素更新到老元素上,由于此节点已经是新节点的第一个节点,所以此时应该操作 dom,把该节点移动到老节点的开头以保持顺序一致,并且老元素的结束索引-1,新元素的开始索引+1,本轮对比结束。下一轮继续将老节点的倒数第二个元素对比新节点的第二个元素,依此类推。如果对比的两个元素不是同一个元素,则开始从老节点中查找新节点。 #### 节点查找对比 如果首尾对比没有找到相同的元素,则需要将新节点未对比的第一个元素与老节点的每一个元素比较。如果未找到,或者新老元素的选择器不同,则说明这是一个全新的元素,直接将该元素放到老节点的未对比部分的开头。如果找到了并且选择器一直,就先更新老元素,然后把老元素移动到老节点的未对比部分的开头。最后将新节点的开始索引+1。 ### 剩余节点处理 如果新老节点有一个先对比完,则说明有元素多余,需要根据不同的情况处理这些元素。 #### 老节点数组遍历完成 如果老节点先遍历完成,则说明还有新节点剩余,把新节点的未对比部分全部插入老节点未对比部分的尾端。 #### 新节点数组遍历完成 如果新节点遍历完成,则说明还有老节点剩余,将老节点未对比的所有元素删除。