事关我对于Vue原理面试题的总结

578 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

写在前面: 前端时间准备提桶跑路,于是乎刷了一波vue面试题,跟了一遍B站杨村长的视频,把一些重要的概念记录总结了一下,内容如下:

事关我对于Vue原理面试题的总结

组件间数据传递的方式

vue2和vue3共有的方式

  • props/emit/emit/on
  • children/children/parent
  • attrs/attrs/listeners
  • ref
  • $root
  • eventbus/mitt
  • vuex/pinia
  • provide/inject

Vue响应式原理

  • vue2数据双向绑定: 通过数据劫持加发布者(订阅者)模式实现的",重写了Object.defineProperty的getter和setter方法从而兼容了数组常用方法。
  1. 实现一个监听器Observer,遍历并监听data里面所有的属性,并使用Object.defin Property把所有的属性都加上getter和setter,如果数据有改变就会触发setter通知订阅者.(核心就是Object.defineProperty)

  2. Dep是订阅器,用来在监听器Observer和订阅者Watcher之间进行统一管理,用Dep.notif来通知Watcher.

  3. 实现一个订阅者Watcher,可以收到属性的变化通知,然后更新视图.

  4. 实现一个指令解析器Compile,对每个节点和属性进行扫描和解析,并根据初始化模板数> 据以及初始化相应的订阅器

  • Vue3响应式数据原理: 通过Porxy代理模式实现(暂不明白底层)

    • Proxy(代理),拦截对data任意属性和方法的任意操作, 包括属性值的读写, 属性的添加, 属性的删除等等.
      • Proxy是一个对象,通过new Proxy(target, handler)来创建,
        • target: 是用来包裹的目标对象
        • handler: 是一个自定义函数,可以为{},但不能为null
      • 常用方法
        • handler.get(target,property,receiver)获取值拦截
        • handler.set(target,property,value,receiver)设置值拦截
        • handler.has(target,prop)in 操作符拦截
    • Reflect(反射),Relflect对象与Proxy对象一样,也是ES6为了操作对象而提供的新的API,可以动态对被代理对象的相应属性进行特定的操作
      • 修改某些Object方法的返回结果,让其变得更合理。
      • 让Object操作都变成函数行为。
      • Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为
        <!--Object.defineProperty()在无法定义属性时,会抛出一个错误,
        而Reflect.defineProperty()则会返回false。-->
        //老写法
            try{
                Object.defineProperty(target,property,attributes);
                //success
            }catch(e){
                //failure
            }

        //新写法
            if(Reflect.defineProperty(target,property,attributes)){
                //success
            }else{
                //failure
            }
        <!--如name inobj和deleteobj[name],而Reflect.has(obj,name)和Reflect.deleteProperty(obj,name)
        让它们变成了函数行为。-->
        //老写法
        'assign' in Object//true
        //新写法
        Reflect.has(Object,'assign')//true
            

区别:

观察者模式只能针对单例属性进行监听,通过遍历data里面的数据,手动添加getter和setter,所以某些方法添加的数据没有触发观察者也就没有响应式,因为复杂类型的数据保存的只是引用地址值,监听不到变化.

代理模式是直接监听对象,只要对象改变都会触发proxy的get,set和has方法。

说说你对虚拟dom的理解

  • 虚拟dom是什么

虚拟的dom对象,用js对象来描述dom结构关系.

  • 有什么优缺点
  1. 频繁的操作dom会非常消耗性能,可以抽象在虚拟dom中进行集中处理,然后再统一进行修改,减少dom操作次数,减少重绘和重排.
  2. 方便跨平台,dom结构是浏览器的,但js对象是不限制平台的,可以在Native(APP)中渲染成控件,可以实现SSR(服务端),以及小程序等等.
  • 虚拟dom如何变成真实dom
  1. template模板通过compile编译成ast树,然后再变成render函数
  2. 然后在mount(挂载)过程中,会执行render函数返回js对象(虚拟dom),最终通过patch方法转换真实dom
  3. 挂载结束后,vue程序进入更新流程,响应式数据发生变化会让组件重新render,从而生成新的虚拟dom,新旧虚拟dom通过diff算法计算差异(同层比较,深度优先),得到最小量的dom操作,然后再通过patch方法转换真实dom.

说说你对diff算法的理解

  • diff算法是干嘛的,什么时候执行以及执行方式

在vue组件中,响应式数据发现变化触发实例执行render函数,会产生新的js对象(虚拟dom),这时需要diff算法来找到新旧虚拟dom的变化,然后再统一的通过patch方法转换真实dom,以便高效更新. patch过程是一个递归的过程

  • vue3的优化

在编译期优化patchflags,blocks等(根据patchflag的值判断是文本,属性,样式等)

To Be Continue