美文网首页前端面试之路
「Vue」面试基本要点以及常考题(一)

「Vue」面试基本要点以及常考题(一)

作者: ybrelax | 来源:发表于2019-02-27 15:17 被阅读0次

    什么是单页面应用

    说白就是无刷新,整个webapp就一个html文件,里面的各个功能页面是javascript通过hash,或者history api来进行路由,并通过ajax拉取数据来实现响应功能。因为整个webapp就一个html,所以叫单页面!

    通俗点来讲,在应用整个使用流程里浏览器由始至终没有刷新,所有的数据交互由ajax完成。
    但是用户体验起来和app一样,有明确的页面区分,即所谓的web app。
    后端: 只是注重数据处理
    前端: 负责逻辑交互,页面渲染。

    数据模型


    简述一下MVVM, 以及对比MVC模型有哪些优势?

    先来看看下图:


    MVVM模型

    这是一个MVVM模型

    1. view: 视图
    2. ViewModel 主要就是理解的话就是ViewModel把用户的状态和行为抽离出来成为一个抽象的对象
    3. mode 实现数据交互
      与mvc相别的优势
    4. mvc 逻辑处理过多,会导致c(控制器)过于庞大,不好维护
    5. 控制器的大部分功能一直到viewModel上,瘦身了model
    6. 双向视图绑定,实时预览(view)
    7. 可以对View或ViewController的数据处理部分抽象出来一个函数处理model。这样它们专职页面布局和页面跳转,它们必然更一步的简化。

    Virtual DOM与原生DOM谁更具有优势

    1. 将 Virtual DOM 作为一个兼容层,让我们还能对接非 Web 端的系统,实现跨端开发。
    2. 同样的,通过 Virtual DOM 我们可以渲染到其他的平台,比如实现 SSR、同构渲染等等。
    3. 实现组件的高度抽象化

    Vue 生命周期

    Vue 实例有一个完整的生命周期,生命周期也就是指一个实例从开始创建到销毁的这个过程。

    • beforeCreated():在实例创建之间执行,数据未加载状态。
    • created():在实例创建、数据加载后,能初始化数据,DOM 渲染之前执行。
    • beforeMount():虚拟 DOM 已创建完成,在数据渲染前最后一次更改数据。
    • mounted():页面、数据渲染完成,真实 DOM 挂载完成。
    • beforeUpadate():重新渲染之前触发。
    • updated():数据已经更改完成,DOM 也重新 render 完成,更改数据会陷入死循环。
    • beforeDestory() 和 destoryed():前者是销毁前执行(实例仍然完全可用),后者则是销毁后执行。

    Vue 的父组件和子组件生命周期钩子执行顺序是什么:
    1、父组建: beforeCreate -> created -> beforeMount
    2、子组件: -> beforeCreate -> created -> beforeMount -> mounted
    3、父组件: -> mounted
    总结:从外到内,再从内到外

    前端路由


    前端路由原理?两种实现方式有什么区别?

    目前前端路由的原理就是通过监听路由的变化来改变视图的变化,并且无需刷新页面。目前实现主要有两种方式。

    • hash模式
    • History模式

    两种模式的区别:

    1. hash模式,兼容性良好,无需后端配合,每次访问的域名不会改变,只是改变#后面的hash值
    2. history无需带#号,但是刷新后导致路劲错误,所以需要后端配置(nginx 指定跳转当前地址)

    组件之间的通信

    详情请点击这里vue通信

    Vue 中怎么自定义指令

    全局注册:

    // 注册一个全局自定义指令 `v-focus`
    Vue
    .directive(
    'focus'
    , {
      
    // 当被绑定的元素插入到 DOM 中时……
      inserted: 
    function
     (el) {
        
    // 聚焦元素
        el.focus()
      }
    })
    

    局部注册:

    directives: {
      focus: {
        
    // 指令的定义
        inserted: 
    function
     (el) {
          el.focus()
        }
      }
    }
    

    常见知识点

    Vue.extend 能做什么

    extend主要是用于拓展组件,比如说拓展一些弹出组件,这个就比较好用

    // 创建构造器
    var Profile = Vue.extend({
      template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
      data: function () {
        return {
          firstName: 'Walter',
          lastName: 'White',
          alias: 'Heisenberg'
        }
      }
    })
    // 创建 Profile 实例,并挂载到一个元素上。
    new Profile().$mount('#mount-point')
    

    通常配合$mount来挂载到组件上去

    $route$router的区别

    $router 为 VueRouter 实例,想要导航到不同 URL,则使用 $router.push 方法。

    $route 为当前 router 跳转对象里面可以获取 name 、 path 、 query 、 params 等。

    query和params区别
    query:

    image.png
    parms: image.png

    mixin和 mixins 区别

    1. mixin: 全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。插件作者可以使用混入,向组件注入自定义的行为。不推荐在应用代码中使用。
    // 为自定义的选项 'myOption' 注入一个处理器。
    Vue.mixin({
      created: function () {
        var myOption = this.$options.myOption
        if (myOption) {
          console.log(myOption)
        }
      }
    })
    
    new Vue({
      myOption: 'hello!'
    })
    // => "hello!"
    
    1. mixins 相当于接受一个混入对象的数组
    var mixin = {
      created: function () { console.log(1) }
    }
    var vm = new Vue({
      created: function () { console.log(2) },
      mixins: [mixin]
    })
    // => 1
    // => 2
    

    keep-alive 组件有什么作用

    如果你需要在组件切换的时候,保存一些组件的状态防止多次渲染,就可以使用 keep-alive 组件包裹需要保存的组件。例如tab页面的切换 链接
    当调用这个组件的时候,只有以下两个钩子函数被调用

    • activated: keep-alive组件激活时调用
    • deactivated: keep-alive组件停用时调用

    vue中data为什么是函数

    组件复用的情况,如果采用data为对象的话,更新了A组件更新了公用组件,结果就会导致其他公用这个共有组件的情况也会改变。
    通过原型链看下具体情况

    var MyComponent = function() {}
    MyComponent.prototype.data = {
      a: 1,
      b: 2,
    }
    // 上面是一个虚拟的组件构造器,真实的组件构造器方法很多
    
    var component1 = new MyComponent()
    var component2 = new MyComponent()
    // 上面实例化出来两个组件实例,也就是通过<my-component>调用,创建的两个实例
    
    component1.data.a === component2.data.a // true
    component1.data.b = 5
    component2.data.b // 5
    

    上面就证实了这一点,如果data是函数的话,就会形成一个自己的作用域,相互不影响

    vue 原理实现

    1. 循环dom树,监听DOM的所有元素。(实现watcher)
    2. 运用了Object.defineProperty(建立订阅者) 中得set (通知变化), get(添加订阅者)方法来实现数据监听
    3. 当数据改变事,发送通知,响应dom

    view响应数据的改变,是通过监听dom上的事件来实现的

    当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。
    每个组件实例都有相应的watcher程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。


    vue原理图

    这种方案得缺点:

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

    vue采用proxy重写后就不会出现这种情况了

    NextTick 原理分析

    nextTick 可以让我们在下次 DOM 更新循环结束之后执行延迟回调,用于获得更新后的 DOM。

    写 React / Vue 项目时为什么要在列表组件中写 key,其作用是什么?

    key的作用:

    1. 更准确
      因为带key就不是就地复用了,在sameNode函数 a.key === b.key对比中可以避免就地复用的情况。所以会更加准确。

    2. 更快
      利用key的唯一性生成map对象来获取对应节点,比遍历方式更快。(这个观点,就是我最初的那个观点。从这个角度看,map会比遍历更快。)

    vue和react都是采用diff算法来对比新旧虚拟节点,从而更新节点。在vue的diff函数中(建议先了解一下diff算法过程)。
    在交叉对比中,当新节点跟旧节点头尾交叉对比没有结果时,会根据新节点的key去对比旧节点数组中的key,从而找到相应旧节点(这里对应的是一个key => index 的map映射)。如果没找到就认为是一个新增节点。而如果没有key,那么就会采用遍历查找的方式去找到对应的旧节点。一种一个map映射,另一种是遍历查找。相比而言。map映射的速度更快。

    vue中 watch 和 computed的不同点

    computed: 具有缓存性,页面重新渲染值不变化,计算属性会立即返回之前的计算结果,而不必再次执行函数
    watch: 无缓存性,页面重新渲染时值不变化也会执行

    相关文章

      网友评论

        本文标题:「Vue」面试基本要点以及常考题(一)

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