vue面试题

作者: 林不羁吖 | 来源:发表于2020-03-27 23:28 被阅读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

    • 1.props/emit+v-on: 通过props将数据⾃上⽽下传递,⽽通过emit和v-on来向上传递信息。
    • 2.EventBus: 通过EventBus进⾏信息的发布与订阅
    • 3.vuex: 是全局数据管理库,可以通过vuex管理全局的数据流
    • 4.attrs/listeners: Vue2.4中加⼊的attrs/listeners可以进⾏跨级的组件通信
    • 5.provide/inject:以允许⼀个祖先组件向其所有⼦孙后代注⼊⼀个依赖,不论组件层次有多深,并在起上下游关系成 ⽴的时间⾥始终⽣效,这成为了跨组件通信的基础

    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可以减少页面的回流和重绘,提升性能

    相关文章

      网友评论

        本文标题:vue面试题

        本文链接:https://www.haomeiwen.com/subject/pgqduhtx.html