超全vue面试题整理

vue基础

vue是什么

是一个动态构建用户界面的渐进式JavaScript框架。用来创建单页应用的 web 应用框架。

优势:Vue 是一个轻量级框架,只关注图层,是一个构建数据的视图集合,大小只有十几KB。vue简单易学,而且通过 MVVM 思想实现了数据的双向绑定,让开发者不用再操作 dom 对象,有更多时间去思考业务逻辑。而且 vue是组件化的,通过组件,将单页应用中的各个模块拆分成单独的组件,提高了复用性。在更新视图的时候,还提供了虚拟节点,将新旧虚拟节点进行对比,然后更新视图。

Vue与React

  • 相同点

    • 都有组件化思想

    • 都是数据驱动视图

    • 都支持服务端渲染

    • 都有虚拟DOM

  • 不同点

    • 数据流向不同。前者是双向数据流,后者是单向数据流。

    • 数据变化的实现原理不同。前者使用的是可变的数据,后者使用的是不可变的数据。

    • diff算法不同。前者使用双指针,边对比,边更新 DOM。后者主要使用 diff 队列保存需要更新的一些 DOM,然后得到patch 树,在统一进行批量更新 DOM。

MVC与MVVM

MVC

  • M(模型层):处理应用程序数据逻辑的部分(存数据、取数据)

  • V(视图层):处理数据显示的部分(页面展示、Dom操作)

  • C(控制层):处理用户交互的部分(控制模型层与视图层的关联)

MVVM

  • M(模型层):处理数据与业务逻辑的部分

  • V(视图层):负责数据展示的部分

  • VM(视图模型层):负责从模型层监听数据的变化从而更新视图层,用来处理用户交互操作的部分

两者最大区别:MVVM 实现了模型层与视图层的自动同步,当数据发生变化时,不用手动操作DOM元素来改变视图层的显示,而是改变了数据对应的视图层自动更新

双向数据绑定(可以看我之前写的vue2双向数据绑定的源码解析Vue2手写源码---响应式数据的变化_想学好前端的小宝的博客-CSDN博客)

vue 采用的是数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() (vue3 通过 Proxy进行劫持)来劫持各个属性的 gettersetter 方法,然后再数据变动的时候,发送消息给订阅者,触发相应的监听回调。主要步骤:

  • 先使用 数据监听器Observe 对数据对象上的所有属性都添加上 getter 和 setter 方法。这样如果数据有发生变动的话,就能拿到最新值。

  • 再使用 compile 进行模板的解析。将模板中的变量替换成数据,然后初始化渲染视图。并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。

  • 创建一个 订阅者 watcher ,在自身实例化时,往属性订阅器dep)中添加自己,然后一旦属性变动,就会调用 dep.notice() 方法通知 对应的 watcher 调用 update() 方法进行更新,从而更新视图。

  • MVVM 作为数据绑定的入口,整合了 Observe、Compile、Watcher三者。通过 Observe 监听 模型层的数据变化,通过 Compile 来编译解析 模板指令,最后通过 Watcher 搭起 Observer 和 Compile 之间的通信桥梁,可以收到属性的变化通知并执行相应的函数,从而达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model 变更的双向绑定效果。

使⽤ Object.defineProperty() 来进⾏数据劫持有什么缺点

在对⼀些属性进⾏操作时,使⽤这种⽅法⽆法拦截,⽐如通过下标⽅式修改数组数据或者给对象新增属 性,这都不能触发组件的重新渲染,因为 Object.defineProperty 不能拦截到这些操作。更精确的来 说,对于数组⽽⾔,⼤部分操作都是拦截不到的,只是 Vue 内部通过重写函数的⽅式解决了这个问题。

Vue3.0 通过使⽤ Proxy 对对象进⾏代理,从⽽实现数据劫持。它可以完美的监听到任何方式的数据改变,唯⼀的缺点是兼容性的问题,因为 Proxy是 ES6 的语法。

computed 与 watch区别

  • 前者支持缓存,只有依赖的数据发生变化时,才会重新计算。后者不支持缓存,只要数据发生变化,就会触发相应操作。

  • 前者不支持异步,有异步就无法监听数据变化。后者支持异步

  • 前者一个属性由另外的属性计算而来的话,这个属性也依赖与另外的属性。

  • 前者的值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data声明过,或者父组件传递过来的props中的数据进行计算的。

  • 后者监听数据必须是data中声明的或者父组件传递过来的props中的数据,当发生变化时,会出大其他操作,函数有两个的参数:

    • immediate:组件加载立即触发回调函数

    • deep:深度监听,发现数据内部的变化,在复杂数据类型中使用,例如数组中的对象发生变化。需要注意的是,deep无法监听到数组和对象内部的变化。

  • 当想要执行异步或者昂贵的操作以响应不断的变化时,就需要使用watch

插槽(slot)

是子组件的一个模板标签元素。

  • 默认插槽:在 slot 没有指定 name 属性值时候,一个默认的显示插槽。

  • 具名插槽:带有 name 属性的 slot, 一个组件可以有多个具名插槽。

  • 作用域插槽:默认插槽、具名插槽的⼀个变体,可以是匿名插槽,也可以是具名插槽,该插槽的不 同点是在⼦组件渲染作⽤域插槽时,可以将⼦组件内部的数据传递给⽗组件,让⽗组件根据⼦组件 的传递过来的数据决定如何渲染该插

常见的事件修饰符

  • .stop: 防止冒泡

  • .prevent: 阻止默认行为(链接跳转)

  • .once: 只会触发一次

  • .capture:进行事件捕捉(由外到内)

  • .self:只会触发自己范围内的事件,不包含子元素。

v-if和v-show的区别

  • 控制手段不同。前者动态的向DOM树内增加或者删除DOM元素来控制元素的显示与隐藏。后者通过 css 中的 display属性来控制元素的显示与隐藏。

  • 前者支持