VUE面试知识整理

  • 谈谈对 keep-alive 的了解?
    keep-alive 是Vue内置的一个组件,可以使被包含的组件保留状态,避免重新渲染,其有以下特性:
    * 一般结合路由和动态组件一起使用,用于缓存组件;
    * 提供 include 和 exclude 属性,两者都支持字符串或正则表达式,include 表示只有名称匹配的组件会被缓存, exclude 表示任何名称匹配的组件都不会被缓存,其中 exclude 的优先级比 include 高;
    * 对应两个钩子函数 activated 和 deactivated,当组件被激活时,触发钩子函数 activated;当组件被移除时,触发钩子函数 deactivated。

  • 父组件可以监听到子组件的生命周期吗?
    比如有父组件Parent和子组件child,如果父组件监听到子组件挂载mounted就做一些逻辑处理,可以通过以下写法实现:

    // Parent.vue
    <Child @mounted="doSomething"/>
    // Child.vue
    mounted(){
      this.$emit("mounted");
    }
    

    以上需要手动通过$emit触发父组件的事件,更简单的方式可以用在父组件引用子组件时通过 @hook 来监听即可,如下所示:

    //Parent.vue
    <Child @hook:mounted="doSomething"></Child>
    doSomething(){
      console.log('父组件监听到 mounted 钩子函数 ...');
    },
    
    //Child.vue
    mounted(){
      console.log('子组件触发  mounted 钩子函数 ... ');
    },
    
    // 以上输出顺序为:
    // 子组件触发  mounted 钩子函数 ... 
    // 父组件监听到 mounted 钩子函数 ...
    

    当然 @hook 方法不仅仅是可以监听 mounted,其他的生命周期事件比如:created, updated 等都可以监听。

  • 在什么阶段才能访问操作DOM?
    在钩子函数mounted被调用前,Vue已经将编译好的模板挂载到页面上了,所以在mounted中可以访问操作DOM。

  • 在哪个生命周期内调用异步请求?
    可以在钩子函数created、beforeMount、mounted中进行调用,因为在这三个钩子函数中,data已经创建,可以将服务端返回的数据进行赋值。但是普遍推荐在created钩子函数中调用异步请求,因为在created钩子函数中调用异步请求有以下优点:

    • 能更快获取到服务端数据,,减少页面loading时间;
    • ssr不支持beforeMount、mounted钩子函数,所以放在created中有助于一致性;
  • 谈谈你对Vue生命周期的理解?
    Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom->渲染、更新-渲染、卸载等一系列过程,称之为Vue的生命周期。

    beforeCreate  --  组件实例被创建之初,组件的属性生效之前; 
    created -- 组件实例已经完全创建,属性也绑定,但真实DOM还不可用;
    beforeMount -- 在挂载开始之前被调用:相关的render函数首次被调用;
    mounted -- el被新创建的vm.$el替换。并挂载到实例上去之后调用;
    beforeUpdate -- 组件数据更新之前调用,发生在虚拟DOM打补丁之前;
    update -- 组件数据更新之后;
    activited -- keep-alive专属,组件被激活时调用;
    deadctivated -- keep-alive专属,组件被销毁时调用;
    beforeDestory -- 组件被销毁前调用;
    destoryed -- 组件被销毁后调用;
    
  • Vue的父组件和子组件生命周期钩子函数执行顺序?
    Vue的父组件和子组件生命周期钩子函数执行顺序可以归类为以下4部分:

    • 加载渲染过程
      父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
    • 子组件更新过程
      父beforeUpdate->子beforeUpdate->子updated->父updated;
    • 父组件更新过程
      父beforeUpdate->父updated;
    • 销毁过程
      父beforeDestroy->子beforeDestroy->子destroyed->父destroyed;
  • 直接给一个数组项赋值,Vue能检测到变化吗?
    由于JavaScript的限制,Vue不能检测到以下数组的变动:

    • 当你利用索引直接设置一个数组项时,例如:

      vm.items[indexOfItem]=newValue;

    • 当你修改数组的长度时,例如:

      vm.items.length=newLength;
      
      //Vue.set
      Vue.set(vm.items,indexOfItem,newValue);
      
      //vm.$set, Vue.set的一个别名
      vm.$set(vm.items,indexOfItem,newValue);
      
      //Array.prototype.splice
      vm.items.splice(indexOfItem, 1, newValue)
      
      //Array.prototype.splice
      vm.items.splice(newLength)
      
      
  • 怎么理解VUE的单向数据流?
    所有的prop都使得其父子prop之间形成了一个单向下行绑定:父级prop的更新会向下流动到子组件中,但是反过来则不行。
    这样可以防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
    额外的,每次父级组件发生更新时,子组件中所有的prop都将会刷新为最新的值。
    这意味着你不应该在一个子组件内部改变prop。如果这样做了,vue会在浏览器的控制台中发出警告。
    子组件想修改prop时,只能通过$emit派发一个自定义事件,父组件接收到后,由父组件修改。
    这个prop用来传递一个初始值;这个子组件接下来希望将其作为一个本地的prop数据来使用。在这种情况下,最好定义一个本地的data属性并将这个prop用作其初始值:

        props: ['initialCounter'],
        data: function(){
          return {
            counter: this.initialCounter,
          }
        }
    

    这个prop以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个prop的值来定义一个计算属性:

        props:['size'],
        computed:{
          normalizedSize: function(){
            return this.size.trim().toLowerCase()
          }
        }
    
  • v-if与v-show有什么区别?
    v-if是真正的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;
    也是惰性的;
    如果在初始渲染时条件为假,则什么也不——直到条件第一次变为真时,才会开始渲染条件快。
    v-show 则简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于css的‘dispaly’属性进行切换。
    所以,v-if适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show则适用于需要非常频繁切换条件的场景。

  • SPA单页面的理解,优缺点?
    SPA(single-page application)仅在web页面初始化时加载相应的HTML/JS和CSS。一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现HTML内容的替换,UI与用户的交互,避免页面的重新加载。
    优点:
    1.用户体验好、快,内容的改变不需要重新加载整个页面,避免不必要的跳转和重复渲染;
    2.SPA相对于服务器的压力较小;
    3.前后端分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
    缺点:
    1.初次加载耗时多,为实现单页Web应用功能及显示效果,需要在加载页面的时候js和css统一加载,部分页面按需加载;
    2.前进后退路由管理,由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;
    3.SEO难度较大,由于所有的内容都在一个页面中动态替换显示,所以在SEO上有其天然的弱势。

  • Class与Style如何动态绑定?
    Class可以通过对象语法和数组语法进行动态绑定:
    对象语法:

      <div v-bind:calss="{active:isActive, 'text-danger': hasError}"></div>
      data:{
        isActive: true,
        hasError: false,
      }
    

    数组语法:

      <div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
      data:{
        activeClass: 'active',
        errorClass: 'text-danger'
      }
    

    Style也可以通过对象语法和数组语法进行动态绑定:
    对象语法:

      <div v-bind:style="{color: activeColor, fontSize + 'px'}"></div>
      data: {
        activeColor: 'red'
        fontSize: 30
      }
    

    数组语法:

      <div v-bind:style="[styleColor, styleSize]"></div>
      data: {
        styleColor: {
          color: 'red'
        },
        styleSize:{
          fontSize:'23px'
        }
      }
    
  • computed和watch的区别和运用的场景?
    computed:是计算属性,依赖其它属性值,并且computed的值有缓存,只有它依赖的属性值发生改变,下一次获取computed的值时才会重新计算computed的值;
    watch:更多的是‘观察’的作用,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作;
    1.当我们需要进行数值计算,并且依赖于其它数据时,应该使用computed,因为可以利用compted的缓存特性,避免每次获取值时,都要重新计算;
    2.当我们需要在数据变化时执行异步或开销较大的操作时,应该使用watch,使用watch选项允许我们执行异步操作(访问一个API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

原文地址:https://www.cnblogs.com/hechen-xuan/p/15176685.html