Vue.js面试题精选—8

71 Vue3.0 是如何变得更快的


diff 方法优化

  • Vue2.x 中的虚拟 dom 是进行全量的对比。
  • Vue3.0 中新增了静态标记(PatchFlag):在与上次虚拟结点进行对比的时候,值对比 带有 patch flag 的节点,并且可以通过 flag 的信息得知当前节点要对比的具体内容化

hoistStatic 静态提升

  • Vue2.x : 无论元素是否参与更新,每次都会重新创建。
  • Vue3.0 : 对不参与更新的元素,只会被创建一次,之后会在每次渲染时候被不停的复用

cacheHandlers 事件侦听器缓存

默认情况下 onClick 会被视为动态绑定,所以每次都会去追踪它的变化但是因为是同一 个函数,所以没有追踪变化,直接缓存起来复用即可

72 说说你对 proxy 的理解


vue 的数据劫持有两个缺点

  • 无法监听通过索引修改数组的值的变化
  • 无法监听 object 也就是对象的值的变化
  • 所以 vue2.x 中才会有$set 属性的存在
  • proxy 是 es6 中推出的新 api,可以弥补以上两个缺点,所以 vue3.x 版本用 proxy 替换 object.defineproperty

73 生命周期详解


*init*

  • initLifecycle/Event,往vm上挂载各种属性

  • callHook: beforeCreated: 实例刚创建

  • initInjection/initState: 初始化注入和 data 响应性

  • created: 创建完成,属性已经绑定, 但还未生成真实dom`

  • 进行元素的挂载: $el / vm.$mount()

  • 是否有

    template

    : 解析成

    render function
    • *.vue文件: vue-loader会将<template>编译成render function
  • beforeMount: 模板编译/挂载之前

  • 执行render function,生成真实的dom,并替换到dom tree

  • mounted: 组件已挂载

update

  • 执行diff算法,比对改变是否需要触发UI更新

  • flushScheduleQueue

  • watcher.before: 触发beforeUpdate钩子 – watcher.run(): 执行watcher中的 notify,通知所有依赖项更新UI

  • 触发updated钩子: 组件已更新

  • actived / deactivated(keep-alive): 不销毁,缓存,组件激活与失活

  • destroy
    • remove(): 删除节点
    • watcher.teardown(): 清空依赖
    • vm.$off(): 解绑监听
    • beforeDestroy: 销毁开始
    • 销毁自身且递归销毁子组件以及事件监听
    • destroyed: 完成后触发钩子

上面是vue的声明周期的简单梳理,接下来我们直接以代码的形式来完成vue的初始化

 new Vue({})

// 初始化Vue实例
function _init() {
// 挂载属性
initLifeCycle(vm)
// 初始化事件系统,钩子函数等
initEvent(vm)
// 编译slot、vnode
initRender(vm)
// 触发钩子
callHook(vm, 'beforeCreate')
// 添加inject功能
initInjection(vm)
// 完成数据响应性 props/data/watch/computed/methods
initState(vm)
// 添加 provide 功能
initProvide(vm)
// 触发钩子
callHook(vm, 'created')

// 挂载节点
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}

// 挂载节点实现
function mountComponent(vm) {
// 获取 render function
if (!this.options.render) {
// template to render
// Vue.compile = compileToFunctions
let { render } = compileToFunctions()
this.options.render = render
}
// 触发钩子
callHook('beforeMounte')
// 初始化观察者
// render 渲染 vdom,
vdom = vm.render()
// update: 根据 diff 出的 patchs 挂载成真实的 dom
vm._update(vdom)
// 触发钩子
callHook(vm, 'mounted')
}

// 更新节点实现
funtion queueWatcher(watcher) {
nextTick(flushScheduleQueue)
}

// 清空队列
function flushScheduleQueue() {
// 遍历队列中所有修改
for(){
// beforeUpdate
watcher.before()

// 依赖局部更新节点
watcher.update()
callHook('updated')
}
}

// 销毁实例实现
Vue.prototype.$destory = function() {
// 触发钩子
callHook(vm, 'beforeDestory')
// 自身及子节点
remove()
// 删除依赖
watcher.teardown()
// 删除监听
vm.$off()
// 触发钩子
callHook(vm, 'destoryed')
}

74 Proxy 相比于 defineProperty 的优势


  • 数组变化也能监听到
  • 不需要深度遍历监听
let data = { a: 1 }
let reactiveData = new Proxy(data, {
get: function(target, name){
// ...
},
// ...
})

75 vue-router


mode

  • hash
  • history

跳转

  • this.$router.push()
  • <router-link to=""></router-link>

占位

<router-view></router-view> 

76 vuex总结


  • state: 状态中心
  • mutations: 更改状态
  • actions: 异步更改状态
  • getters: 获取状态
  • modules: 将state分成多个modules,便于管理

77 diff 算法


时间复杂度: 个树的完全diff 算法是一个时间复杂度为O(n*3) ,vue进行优化转化成O(n)

理解:

  • 最小量更新,

    key

    很重要。这个可以是这个节点的唯一标识,告诉

    diff

    算法,在更改前后它们是同一个DOM节点

    • 扩展v-for 为什么要有key ,没有key 会暴力复用,举例子的话随便说一个比如移动节点或者增加节点(修改DOM),加key 只会移动减少操作DOM。
  • 只有是同一个虚拟节点才会进行精细化比较,否则就是暴力删除旧的,插入新的。

  • 只进行同层比较,不会进行跨层比较。

diff算法的优化策略:四种命中查找,四个指针

  1. 旧前与新前(先比开头,后插入和删除节点的这种情况)
  2. 旧后与新后(比结尾,前插入或删除的情况)
  3. 旧前与新后(头与尾比,此种发生了,涉及移动节点,那么新前指向的节点,移动到旧后之后)
  4. 旧后与新前(尾与头比,此种发生了,涉及移动节点,那么新前指向的节点,移动到旧前之前)

78 Vue 的响应式原理中 Object.defineProperty 有什么缺陷


  • Object.defineProperty 无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
  • Object.defineProperty 只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。Proxy 可以劫持整个对象,并返回一个新的对象
  • Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性

79 Composition API


  • Composition API出现就是为了解决Options API导致相同功能代码分散的现象
Vue.js面试题精选---8
img

compositon api提供了以下几个函数:

  • setup
  • ref
  • reactive
  • watchEffect
  • watch
  • computed
  • toRefs
  • 生命周期的hooks

80 vue中是如何检测数组变化的呢


数组就是使用 object.defineProperty 重新定义数组的每一项,那能引起数组变化的方法我们都是知道的, poppushshiftunshiftsplicesortreverse 这七种,只要这些方法执行改了数组内容,我就更新内容就好了,是不是很好理解

  • 是用函数劫持的方式,重写了数组方法,具体呢就是更改了数组的原型,更改成自己的,用户调数组的一些方法的时候,走的就是自己的方法,然后通知视图去更新
  • 数组里每一项可能是对象,那么我就是会对数组的每一项进行观测,(且只有数组里的对象才能进行观测,观测过的也不会进行观测)

vue3:改用 proxy ,可直接监听对象数组的变化

原文始发于微信公众号(消失的程序员):Vue.js面试题精选—8

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/250893.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!