# fed-e-task-03-02 **Repository Path**: vvweb/fed-e-task-03-02 ## Basic Information - **Project Name**: fed-e-task-03-02 - **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-07-29 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ###第一题 请简述Vue首次渲染的过程。 1.首先执行vue实例的_init函数 2._init执行_init方法,内部实现了响应式数据,在函数最后面执行了$mount 3.挂载整个页面,如果传入render函数的话,获取render函数,如果没有的话,就将template或者el的outerHTML编译成render函数,同时生成当前组件的渲染Watcher,将render函数作为回调函数传入 4.渲染Watcher被创建的时候,就会开始执行对应的get,也就是render函数 5.在render函数中,会获取当前data中的数据,这样就会触发数据响应式中的getter函数,进行依赖收集 6.这样在以后的数据更新中,就会执行对应的渲染watcher了 7.然后将render生成的vnode生成对应的dom节点挂载到页面上 8.移除el节点 ![vue初始化渲染过程](./vue初始化渲染过程.png) ###第二题 请简述Vue响应式原理。 1.设置响应式数据(给数据设置setter,getter),每个vue实例都有一个watcher对象,当触发getter时当前属性会有一个dep实例收集当前vue实例的watcher对象,触发setter时会遍历dep中收集的watcher实例执行watcher的update方法执行对应的更新操作 2.当前数据为数组的时候,就修改数组的proto的指向,指向自定义的函数集,其主要还是在执行完毕之后,执行了ob.dep.notify()函数,通知渲染watcher进行改变 3.当前数据为对象时,遍历对象的每一个值,进行响应式处理 4.当前数据为computed时,设置当前的lazy和dirty为true,只有当依赖的数据改变了之后,才会改变dirty为true,这样在执行当前computed的getter的时候会调用当前依赖的watcherevaluate,获取当前computed的值的同时,将dirty置为false,让下次获取从缓存中拿 5.当前数据为watch侦听器的时候,调用$watch,然后创建用户watcher,将传入的handler传入作为cb 6.然后在渲染watch初始化的时候,就会执行一遍cb,执行render函数 7.依赖收集以后Watcher对象会被保存在Dep的subs中,定义getter,收集依赖 8.定义setter 1.原有值和新值比较,值一样则不做处理 2.如果是新值对象,则调用observer 3.派发更新(发送通知),调用dep.notify() ![vue响应式原理](./vue响应式原理.png) ###第三题 请简述虚拟DOM中Key的作用和好处。 作用:可以让vnode在diff的过程中找到对应的节点,便它能够跟踪每个节点的身份,从而重用和重新排序现有元素。 好处:减少dom的操作,减少diff和渲染所需要的时间 ###第四题 请简述Vue中模板编译的过程。 1.缓存公共的mount函数,并重写浏览器平台的mount 2.判断是否传入了render函数,就去调用compile函数,在compile函数中,首先去合并选项,然后调用baseCompile函数编译模板。 3.将模板编译成AST抽象语法树 4.优化抽象语法树,设置静态节点和静态根节点(只包含纯文本的静态节点不是静态根节点,因为此时的优化成本大于收益) 5.通过generate将AST抽象语法树转换为render函数的js字符串 6.将render函数通过createFunction函数转换为一个可以执行的函数 7.当render和staticRenderFns初始化完毕,挂载到Vue实例的options对应的属性上。