# fed-e-task-03-01 **Repository Path**: zuojinsheng/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-01-20 - **Last Updated**: 2021-01-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 简答题 1. 不是,可以通过使Vue.set(dog, 'name', 'Trump') 或者 this.$set(dog, 'name', 'Trump')。 通过分析 Vue 源码 function set(target, key, val)方法得知: 1)如果 target 未定义(null或者undefined)或者 target 为基础数据类型时,会抛出异常 2)如果 target 为数组并且key为有效的数组key时,将数组的长度设置为target.length,并且使用 splice方法向数组中添加元素 3)如果属性 key 存在于target上并且 key 不属于原型对象上的属性时,表示在修改target对象属性为 key 的值 4)判断 target 是否为 Vue 实例或者根数据 data 对象是时,如果是,则抛出异常 5)判断 target 是否为响应式数据,如果不是则按照普通对象添加属性的方式来处理,如果是响应式则将target的属性key通过defineReactive$$1(ob.value, key, val)方法设置成响应式并通过ob.dep.notify()方法手动触发通知属性值的更新 2. 当调用 patch 函数时,先去判断旧节点是否为 vnode,不是则转换为 vnode;然后判断新旧 vnode 是否 在 updateChildren 中,传入的新旧 vnode 的children 数组,比对两个数组先从两个数组的第一个开始,如果相同则比对的指针后移到下一轮循环,如果不同则比对从两个数组的最后一个,相同则前移到下一轮循环,如果还不同则从旧节点 children 数组的第一个跟新节点 children 数组的最后一个对比,如果相同则把旧 children 数组的第一个移动到当前指针的最后面,更新对应指针到下一轮循环;如果还不同则比对 旧 children 数组的最后一个和新 children 数组的第一个,如果相同则把旧 children 数组的最后一个移动到当前指针的最前面,更新指针到下一轮循环; 如果这四种情况都不满足,则拿当前旧 children 的前后指针遍历后,根据 key 生成 map,以新 children 数组当前指针对象的key 去map 中找,如果找不到说明是新元素,则插入到 dom 中,如果找到了再去比对 map 对应的旧 children 指针节点的sel 和当前遍历新 children 中指针节点的sel 是否相同,不同则插入 DOM,相同则递归调用 patchVnode,并且插入 DOM; 最后,对比两个数组的开始和结束指针,如果在开始小于等于结束指针,判断如果旧节点数组开始指针大于结束指针,说明新节点没遍历完,此时根据新节点数组的开始结束指针,把数组剩下的内容插入到 DOM 中;如果旧节点数组开始指针小于等于结束指针,说明旧节点没遍历完,根据指针移除剩余的旧节点; # 编程题 1. 模拟 VueRouter [代码](./code/case-1/src/vueRouter) 实现思路: * 创建vueRouter类,类中定义静态install方法、constructor、init方法、initRouteMap方法、initComponents方法、initEvent方法 * install方法中判断当前插件是否已经安装,如果没有安装把插件置为安装状态。把Vue构造函数传给全局变量,后续使用。通过Minin(混入)方法把创建Vue实例时候传入的router对象注入到Vue实例上,给Vue原型上添加$router,并调用$router的init方法 * constructor构造函数中记录传入的options的值、定义routeMap记录options中的routes解析出来的值、设置data为响应式记录current地址,通过判断options.mode类型设置current的地址。设置初始化浏览器地址的格式 * init初始化initRouteMap、initComponent、initEvent方法 * initRouteMap把options当中的routes解析成键值对的形式存储到routeMap当中 * initComponents注册通过Vue.component注册router-link和router-view组件 * initEvent注册popstate和hashchange时间,通过mode值分别注册不同的事件 2. 模拟Vue.js响应式 [代码](./code/case-2) 3. snabbdom实现 [代码](./code/case-3)