面试题

vue面试题

2020-03-27  本文已影响0人  林不羁吖

1.你对MVVM的理解?

1.1 MVVM是什么?

Model 层: 对应数据层的域模型,它主要做域模型的同步。在层间关系⾥,它主要⽤于抽象出 ViewModel 中视图的 Model。

View 层:作为视图模板存在,在 MVVM ⾥,整个 View 是⼀个动态模板。除了定义结构、布局外,它展示的是 ViewModel 层的数据和状态。View 层不负责处理状态,View 层做的是 数据绑定的声明、 指令的声明、 事件绑定的声 明。

ViewModel 层:把 View 需要的层数据暴露,并对 View 层的 数据绑定声明、 指令声明、 事件绑定声明 负责,也就是处 理 View 层的具体业务逻辑。ViewModel 底层会做好绑定属性的监听。当 ViewModel 中数据变化,View 层会得到更新;⽽当 View 中声明了数据的双向绑定(通常是表单元素),框架也会监听 View 层(表单)值的变化。⼀旦值变 化,View 层绑定的 ViewModel 中的数据也会得到⾃动更新。

1.2 MVVM的优缺点?

优点:

  1. 分离视图(View)和模型(Model),降低代码耦合,提⾼视图或者逻辑的重⽤性: ⽐如视图(View)可以独⽴于

Model变化和修改,⼀个ViewModel可以绑定不同的"View"上,当View变化的时候Model不可以不变,当Model变化 的时候View也可以不变。你可以把⼀些视图逻辑放在⼀个ViewModel⾥⾯,让很多view重⽤这段视图逻辑

  1. 提⾼可测试性: ViewModel的存在可以帮助开发者更好地编写测试代码

  2. ⾃动更新dom: 利⽤双向绑定,数据更新后视图⾃动更新,让开发者从繁琐的⼿动dom中解放

缺点:

  1. Bug很难被调试: 因为使⽤双向绑定的模式,当你看到界⾯异常了,有可能是你View的代码有Bug,也可能是Model 的代码有问题。数据绑定使得⼀个位置的Bug被快速传递到别的位置,要定位原始出问题的地⽅就变得不那么容易 了。另外,数据绑定的声明是指令式地写在View的模版当中的,这些内容是没办法去打断点debug的
  2. ⼀个⼤的模块中model也会很⼤,虽然使⽤⽅便了也很容易保证了数据的⼀致性,当时⻓期持有,不释放内存就造 成了**花费更多的内存 **
  3. 对于⼤型的图形应⽤程序,视图状态较多,ViewModel的构建和维护的成本都会⽐较⾼

2.你对Vue⽣命周期的理解?

2.1 ⽣命周期是什么

Vue 实例有⼀个完整的⽣命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom -> 渲染、更新 -> 渲染、卸载 等⼀系列过程

2.2 各个⽣命周期的作⽤

2.3 异步请求适合在哪个⽣命周期调⽤?

官⽅实例的异步请求是在mounted⽣命周期中调⽤的,⽽实际上也可以在created⽣命周期中调⽤。

3.Vue组件如何通信?

https://juejin.im/post/5d267dcdf265da1b957081a3

4.computed和watch有什么区别?

computed用于计算属性,只有它依赖的值改变才会触发,且这个值有缓存

watch用于监听一个属性的变化,属性变化就会触发


computed:

  1. computed 是计算属性,也就是计算值,它更多⽤于计算值的场景
  2. computed 具有缓存性,computed的值在getter执⾏后是会缓存的,只有在它依赖的属性值改变之后,下⼀次获取 computed的值时才会重新调⽤对应的getter来计算
  3. computed 适⽤于计算⽐较消耗性能的计算场景
    watch:
  4. 更多的是「观察」的作⽤,类似于某些数据的监听回调,⽤于观察 props $emit 或者本组件的值,当数据变化时来执 ⾏回调进⾏后续操作
  5. ⽆缓存性,⻚⾯重新渲染时值不变化也会执⾏

⼩结:

  1. 当我们要进⾏数值计算,⽽且依赖于其他数据,那么把这个数据设计为computed
  2. 如果你需要在某个数据变化时做⼀些事情,使⽤watch来观察这个数据变化

5.Vue是如何实现双向绑定的?

简单版:利⽤ Object.defineProperty 劫持对象的访问器,在属性值发⽣变化时我们可以获取变化,然后根据变化进⾏后续响应,在 vue3.0中通过Proxy代理对象进⾏类似的操作。

// 这是将要被劫持的对象 
const data = {
  name: '',
};

function say(name) {
  if (name === '古天乐') {
    console.log('给⼤家推荐⼀款超好玩的游戏');
  } else if (name === '渣渣辉') {
    console.log('戏我演过很多,可游戏我只玩贪玩懒⽉');
  } else {
    console.log('来做我的兄弟');
  }
}
// 遍历对象,对其属性值进⾏劫持 
Object.keys(data).forEach(function (key) {
  Object.defineProperty(data, key, {
    enumerable: true,
    configurable: true,
    get: function () {
      console.log('get');
    },
    set: function (newVal) {
      // 当属性值发⽣变化时我们可以进⾏额外操作 
      console.log(`⼤家好,我系${newVal}`);
      say(newVal);
    },
  });
});
data.name = '渣渣辉'; 
//⼤家好,我系渣渣辉 
//戏我演过很多,可游戏我只玩贪玩懒⽉

补充
vue的双向绑定是通过数据劫持和发布者-订阅者模式实现的,数据劫持又是通过
Object.defineProperty()实现的

5.1 Object.defineProperty

Object.defineProperty(data,'a',{
    enumerable:true,//是否可枚举
    writable:true,//是否可写
    configurable:true,//是否可配置
    get(){
        return this.a//读取data对象的a属性时,触发get方法
    },
    set(val){
        this.a=val;//修改data对象的a属性时,触发set方法
    }
})

5.2 mvvm的数据变化更新视图,是通过Object.defineProperty()实现的;视图更新变化数据,是通过事件监听实现的。

5.3 发布者-订阅者的实现过程:

  1. 实现一个监听器Observer,劫持并监听所有属性,如果有变化,就通知订阅者
  2. 实现一个订阅者Watcher,收到属性的变化通知并执行响应的函数,从而更新视图
  3. 实现一个解析器Compiler,可以扫描并解析每个节点的相关指令,初始化模板数据和对应的订阅器

6.Proxy与Object.defineProperty的优劣对⽐?

Proxy的优势如下:
Proxy可以直接监听对象⽽⾮属性
Proxy可以直接监听数组的变化
Proxy有多达13种拦截⽅法,不限于apply、ownKeys、deleteProperty、has等等是 Object.defineProperty 不具备的
Proxy返回的是⼀个新对象,我们可以只操作新的对象达到⽬的,⽽
Object.defineProperty 只能遍历对象属性直接修 改Proxy作为新标准将受到浏览器⼚商重点持续的性能优化,也就是传说中的新标准的性能红利

Object.defineProperty的优势如下: 兼容性好,⽀持IE9

7.你是如何理解Vue的响应式系统的?

8.vue的指令有哪些

v-if 用于条件渲染
v-show 用于条件渲染,两者的区别请参考下一个问题
v-for 用于列表渲染
v-on 监听事件
v-bind 动态绑定
v-html 渲染html元素
v-model 数据双向绑定

9.v-if和v-show区别

v-if 是惰性的,只有条件为真时才会切换,为假时什么也不做。确保切换过程中的事件监听器和子组件适当的被销毁和重建,适用于运行条件很少改变的场景。v-show 不管条件是否为真,总是会被渲染,适用于频繁切换的场景

10.v-for和v-if为什么不能放于同一级

v-for优先级高于v-if,放于同级可能会重复渲染两次v-if,建议把v-for放于v-if所在的外层元素

11.nextTick

原理:eventloop事件循环
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

12.v-for中key的原理

key 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。不指定key时,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试
就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。

有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。

13.生命周期

1.beforeCreate
初始化界面前
2.created
初始化界面后,拿到data,props,methods、computed和watch
3.beforeMount
渲染dom前
4.mounted
渲染dom后,拿到$el
5.beforeUpdate
更新前
6.updated
更新后,拿到更新后的dom
7.beforeDestroy
卸载组件前
8.destroyed
卸载组件后
9.activated
被 keep-alive 缓存的组件激活时调用
10.deactivated
被 keep-alive 缓存的组件停用时调用

  1. errorCaptured
    当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例
    以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

14.vnode的diff算法原理

虚拟dom是对真实dom的一种映射,新旧Vnode比较同层级的节点,然后根据两者的差异只更新有差异的部分,生成新的视图,而不是对树进行逐层搜素遍历,因此时间复杂度是O(n)。虚拟dom可以减少页面的回流和重绘,提升性能

上一篇下一篇

猜你喜欢

热点阅读