# camp 3-1 VueRouter 响应式原理 VNode和Diff **Repository Path**: hj-min/fed-e-task-03-01 ## Basic Information - **Project Name**: camp 3-1 VueRouter 响应式原理 VNode和Diff - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2020-10-06 - **Last Updated**: 2021-11-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 手写 Vue Router、手写响应式实现、虚拟 DOM 和 Diff 算法 ------ ### 一、简答题 1、当我们点击按钮的时候动态给 data 增加的成员是否是响应式数据,如果不是的话,如何把新增成员设置成响应式数据,它的内部原理是什么。 ```js let vm = new Vue({ el: '#el' data: { o: 'object', dog: {}}, method: { clickHandler () { // 该 name 属性是否是响应式的 this.dog.name = 'Trump' } } }) ``` 点击按钮增加的成员,不是响应式数据。 内部原理:Vue 内部仅在 data 初始化,以及重新赋值给新对象时,会将对象成员处理成响应式数据。clickHandler 内部 直接增加属性不会经过响应式处理。 如果要实现响应式数据,有一下几种方式: ```js // 1. 赋值为新对象 this.data = { name: 'Trump' }; // 2. 向响应式对象中添加一个 property this.$set(this.dog, 'name', 'Trump') ``` 2、请简述 Diff 算法的执行过程 同级别子节点一次比较,再找下一级别的节点比较,算法时间复杂 O(n)。 - 同级别比较时,首先对新老节点数组的开始和结尾设置标记索引。 - 再对比开始和结束节点的比较,共四种情况: - oldStartVnode / newStartVnode (旧开始节点 / 新开始节点),如果是 sameVnode(key, sel 相同) - 调用 patchVnode() 对比和更新节点 - 旧开始和新开始索引后移 - oldEndVnode / newEndVnode (旧结束节点 / 新结束节点) 相同 - 调用 patchVnode() 对比和更新节点 - 旧结束和新结束索引前移 - oldStartVnode / newEndVnode (旧开始节点 / 新结束节点) 相同 - 调用 patchVnode() 对比和更新节点 - 把 oldStartVnode 对应的 DOM 元素,移动到右边 - 更新索引 - oldEndVnode / newStartVnode (旧结束节点 / 新开始节点) 相同 - 调用 patchVnode() 对比和更新节点 - 把 oldEndVnode 对应的 DOM 元素,移动到左边 - 更新索引 - 不满足以上四种情况: - 遍历新节点,使用 newStartNode 的 key 在老节点数组中找相同节点 - 如果没有找到,说明 newStartNode 是新节点,创建新节点对应的 DOM 元素,插入到 DOM 树中 - 如果找到了,判断新节点和找到的老节点的 sel 选择器是否相同,如果不相同,说明节点被修改了,重新创建对应的 DOM 元素,插入到 DOM 树中。如果相同,把 elmToMove 对应的 DOM 元素,移动到左边 - 遍历结束:(oldStartIdx > oldEndIdx) 或 (newStartIdx > newEndIdx) - 如果老节点的数组先遍历完 (oldStartIdx > oldEndIdx),说明新节点有剩余,把剩余节点批量 插入到右边 - 如果新节点的数组先遍历完 (newStartIdx > newEndIdx),说明老节点有剩余,把剩余节点批 量删除 ### 二、编程题 1、模拟 VueRouter 的 hash 模式的实现,实现思路和 History 模式类似,把 URL 中的 # 后面的内容作为路由的地址,可以通过 hashchange 事件监听路由地址的变化。 详见目录:`code/mini-vue-router` 2、在模拟 Vue.js 响应式源码的基础上实现 v-html 指令,以及 v-on 指令。 详见目录:`code/mini-vue` 3、参考 Snabbdom 提供的电影列表的示例,利用 Snabbdom 实现类似的效果,如图: 详见目录:`code/snabbdom-demo`