Vue⾯试题进阶(含底层源码原理)
前置
需要看过源码为基础,因为这些问题基本上都是从 源码中到的答案,我只是顺便⾃⼰在看源码时记录了下来.
正⽂
1.Vue 的初始化过程(new Vue(options))都做了什么?
false是什么函数处理组件配置项
初始化根组件时进⾏了选项合并操作,将全局配置合并到根组件的局部配置上
初始化每个⼦组件时做了⼀些性能优化,将组件配置对象上的⼀些深层次属性放到 vm.$options 选项中,以提⾼代码的执⾏效率初始化组件实例的关系属性,⽐如 $parent、$children、$root、$refs 等
处理⾃定义事件
调⽤ beforeCreate 钩⼦函数
初始化组件的 inject 配置项,得到 ret[key] = val 形式的配置对象,然后对该配置对象进⾏响应式处理,并代理每个 key 到 vm 实例上
数据响应式,处理 props、methods、data、computed、watch 等选项
解析组件配置项上的 provide 对象,将其挂载到 vm._provided 属性上,如果 provide 是函数就⽤ call(vm) ⽅法 返回 provide ⾥⾯定义的对象
调⽤ created 钩⼦函数
如果发现配置项上有 el 选项,则⾃动调⽤ $mount ⽅法,也就是说有了 el 选项,就不需要再⼿动调⽤ $mount ⽅法,反之,没提供el 选项则必须调⽤ $mount
接下来则进⼊挂载阶段
⾯试问题
1.⽗组件调⽤⼦组件⾃定义事件时,是谁在监听这个事件?
答案: ⼦组件本⾝,也就是谁触发事件谁就监听,⼦组件会通过⽗组件获取 ,最终编译成 this.$emit(evenName,params) this.$on(eventName,handelrFn)
2.beforeCreate 期间能拿到数据吗?
答案: 不能,因为数据初始化阶段是在 beforeCreate 之后执⾏
3.provide 和 inject 原理
答案:provide 其实不是真正的在根组件中注⼊,⽽是 ⼦组件中的 inject 先根据 key值 ⽣成数组,然后根据数组的长度依次遍历,并且向上级查有没有 provide 这个配置选项,如果有那么就会看有没有 跟当前key 值 匹配,如果匹配的话 就会把value 值赋值给这个key。如果没有 provide ,那么他会继续往上
2puted 缓存原理
computed 本⾝就是⼀个 watcher ,源码中在 vue 初始化阶段的 initComputed 函数中 ,创建了⼀个 watcher 实例,并传进去了⼀个lazy ,lazy 是⼀个布尔值,lazy 本⾝是以常量声明的,所以不可更改,lazy 默认值为 true,然后 watcher 内部会以 lazy 在声明⼀个dirty 属性,这个属性就是 computed 懒执⾏的根本原理,如果 watcher.dirty 为 true ,watcher 构造函数内部 会根据 watcher.evaluate 先将watcher.dirty 置为 false,再执⾏计算属性中的函数,并将其函数返回值 赋值给 watcher.value 属性中,这也就为什么计算属性中的函数要写 return 的原因,当 watcher.dirty 属性为 false 后,就不会在
执⾏ watcher.evaluate ⽅法,也就不会在执⾏ 计算属性中的函数,他最后会直接 return watcher.value 也就是计算属性中的函数执⾏结果,当页⾯更新时(也就是响应式派发更新的时候) set函数会调⽤watcher 中的 update⽅法,在update⽅法中会将 dirty 再次更改为 true,然后此时 计算属性会重新执⾏
3puted 和 watch 哪⾥不同?
其实computed 和 watch 都是⼀个 watcher ,真要说不同的话,我认为有三点
->1puted 默认是懒执⾏,且不可更改(上⾯已经说过了)
-> 2.使⽤场景⽅⾯,watch 可以执⾏⼀些异步操作,⽽ computed ⼤多数为同步操作,可以在 computed 内部的函数加个 async 试试,模板最终渲染为 [object Promise]
-> 3. 当⼀个属性受多个属性影响的时候就需要⽤到 computed ,最典型的栗⼦:购物车商品结算的时候。当⼀条数据影响多条数据的时候就需要⽤ watch ,栗⼦:搜索数据
4. Vue.set( target<Array,Object> , key,val ) 都做了什么
因为 Vue ⽆法探测普通的新增 property (⽐如 wProperty = 'hi'),所以通过 Vue.set 为向响应式对象中添加⼀个property,可以确保这个新 property 同样是响应式的,且触发视图更新。
更新数组指定下标的元素:Vue.set(array, idx, val),内部通过 splice ⽅法实现响应式更新,target.splice(key, 1 , val)
为对象添加⼀个新的响应式数据:调⽤ defineReactive ⽅法为对象增加响应式数据,然后执⾏ ify 进⾏依赖通知,更新视图5.Vue.use(plugin) 做了什么?
⾸先判断该插件是否已经安装过
如果没有,则执⾏插件提供的 install ⽅法安装插件,具体做什么有插件⾃⼰决定
6.Vue.mixin(options) 做了什么?(全局混⼊)
负责在 Vue 的全局配置上合并 options 配置。然后在每个组件⽣成 vnode 时会将全局配置合并到组件⾃⾝的配置上来。
标准化 options 对象上的 props、inject、directive 选项的格式
处理 options 上的 extends 和 mixins,分别将他们合并到全局配置上
然后将 options 配置和全局配置进⾏合并,选项冲突时 options 配置会覆盖全局配置
7.Vueponent(compName, Comp) 做了什么?(注册全局组件)
负责注册全局组件。其实就是将组件配置注册到全局配置的 components 选项上(optionsponents),然后各个⼦组件在⽣成vnode 时会将全局的 components 选项合并到局部的 components 配置项上。
如果第⼆个参数为空,则表⽰获取 compName 的组件构造函数
如果 Comp 是组件配置对象,则使⽤ d ⽅法得到组件构造函数,否则直接进⾏下⼀步
在全局配置上设置组件信息,this.optionsponentspName = CompConstructor
8.Vue 的 nextTick API 是如何实现的?
因为vue 中更新 DOM 是异步刷新的,⽽ nextTick 函数是会在下次 DOM 更新后执⾏
nextTicke 会将传⼊的函数包装⼀次 try / catch 然后push 到 callbacks 数组中,然后调⽤ timerFunc ⽅法将 flushCallBacks ⽅法放到浏览器的异步队列中,当同步任务执⾏完后,调⽤异步队列中的函数 ,此时flushCallBacks ⽅法会将 callBacks 数组遍历 并依次执⾏callBacks 数组中的每⼀个函数
9.vm.$on(event, callback) 做了什么
监听当前实例上的⾃定义事件,事件可由 vm.$emit 触发,回调函数会接收所有传⼊事件触发函数(vm.$emit)的额外参数。
vm.$on 的原理很简单,就是处理传递的 event 和 callback 两个参数,将注册的事件和回调函数以键值对的形式存储到 vm._event 对象中,vm._events = { eventName: [cb1, cb2, ...], ... }。
10.vm.$emit(eventName, [...args]) 做了什么?
触发当前实例上的指定事件,附加参数都会传递给事件的回调函数。
其内部原理就是执⾏ vm._events[eventName] 中所有的回调函数。
11.vm.$off([event, callback]) 做了什么?
移除⾃定义事件,即移除 vm._events 对象上相关数据。
如果没有提供参数,则移除实例的所有事件监听
如果只提供了 event 参数,则移除实例上该事件的所有
如果两个参数都提供了,则移除实例上该事件对应的
12.runtime-complier 解析过程:
1. 将template模板转换成抽象语法树(ast);
2. 通过render函数将抽象语法树转换成虚拟DOM(vdom);
3. 将虚拟DOM转换成真正的DOM;
4. template => 抽象语法树(ast) => render() => 虚拟DOM(vdom) => 页⾯13.runtime-only 解析过程:
1. vue-template-compiler插件直接将组件转换成 render函数;
2. 将render函数返回的虚拟DOM转换成页⾯;
3. render() => 虚拟DOM(vdom) => 页⾯;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。