• vue面试总结2022


    1.vue生命周期及各周期得特点

    beforCreate

    特点:

    初始化实例,不能使用data和methods、ref

    示例

    beforeCreate: function () {
      console.group('------beforeCreate创建前状态------');
      console.log("%c%s", "color:red", "el     : " + this.$el); //undefined
      console.log("%c%s", "color:red", "data   : " + this.$data); //undefined
      console.log("%c%s", "color:red", "data中的msg   : " + this.msg); //undefined
      console.log("%c%s", "color:red", "methods中的handleOpen方法   : " + this.handleOpen); //undefined
    },
    

    结果

    created

    特点:

     data和methods都已经被初始化好了,可以调用,但ref还是不行

    示例

     created: function () {
        console.group('------created创建完毕状态------');
        console.log("%c%s", "color:red", "el     : " + this.$el); //undefined
        console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化 [object Object]
        console.dir(this.$data)
        console.log("%c%s", "color:red", "data中的msg   : " + this.msg); //测试
        console.log("%c%s", "color:red", "methods中的handleOpen方法   : " + this.handleOpen); //function () { [native code] }
      },

    结果

    beforeMount

    特点:

     开始挂载之前调用,相关的render函数首次被调用 此时的DOM是数据挂载前的DOM,数据还未挂载(将虚拟Dom转变成真实Dom的过程,所以在这之前,我们的el当然还是拿不到的)虽然 $ref已被初始化,但还是拿不到值

    示例

    beforeMount: function () {
    console.group('------beforeMount挂载前状态------');
    console.log("%c%s", "color:red", "el : " + this.$el); //undefined
    console.log("%c%s", "color:red", "refs : " + this.$refs); //已被初始化
    console.dir(this.$refs)
    var _ref = JSON.parse(JSON.stringify(this.$refs))
    console.log("%c%s", "color:red", "_ref : " + _ref); //已被初始化
    console.dir(_ref)
    console.log("%c%s", "color:red", "refs.myRef : " + this.$refs.myRef); //undefined
    console.log("%c%s", "color:red", "data : " + this.$data); //已被初始化
    console.log("%c%s", "color:red", "data中的msg : " + this.msg); //已被初始化
    console.log("%c%s", "color:red", "methods中的handleOpen方法 : " + this.handleOpen);//已被初始化
    },

    结果 

     跑题·······················

     大家看小颖在打印 $ref 时 又重新定义了一个_ref ,并且这个变量是深拷贝了 $ref 的,这是为 了方便大家能够看到在该钩子函数中 $ref 的值,如果大家不明白为什么,可以看下下面的代码

        var a = 1;
        var b = a;
        a = 3
        console.log(a)
        console.log(b)
        var a2 = {}
        var b2 = a2
        a2.c = '22'
        console.log(a2)
        console.log(b2)
    

      

    看这个结果大家有没有发现变量  b  不会随着变量  a   的改变而改变,但是变量  b2 会随着变量  a2 的改变而改变,这是为什么呢?

    因为 a 、 b  都是基本类型,而  a2b2 都是引用类型,基本类型存储的是值,引用类型存储的是一个指向对象真实内存地址的指针。在 js 中,对象包括Array Object Function RegExp Math等。

     

     大家可以参考下:js对象赋值只保留存在的属性_夯实JS主要知识点

    来来来,我们接着看vue的生命周期,不要被小颖带偏了哈哈哈

    mounted

    特点:

    实例挂载完成,vue实例已经初始化完成,初始化的el被vm.$el替换(虚拟Dom已经挂载在了真实的元素上,所以从此开始我们就可以拿到el

    示例

      mounted: function () {
        console.group('------mounted 挂载结束状态------');
        console.log("%c%s", "color:red", "el     : " + this.$el); //已被初始化
        console.dir(this.$el)
        console.log("%c%s", "color:red", "refs     : " + this.$refs); //已被初始化
        console.log("%c%s", "color:red", "refs.myRef     : " + this.$refs.myRef);//已被初始化
        console.dir(this.$refs)
        console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化
        console.log("%c%s", "color:red", "data中的msg   : " + this.msg); //已被初始化
        console.log("%c%s", "color:red", "methods中的handleOpen方法   : " + this.handleOpen);//已被初始化
      },
    

    结果 

    beforeUpdate

    特点:

    数据更新时调用,发生在虚拟DOM打补丁之前,这里适合更新之前访问现有的DOM,比如手动移除已添加的时间监听器,该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行 。

    示例

      beforeUpdate: function () {
        console.group('beforeUpdate 更新前状态===============》');
        // 比如点击新增数组元素, vue会触发此生命周期函数, 但是此时页面并未更新, 所以获取不到新增的li标签
        console.log(document.getElementById("myUl").children[2].innerHTML);
        console.log(document.getElementById("myUl").children[3].innerHTML);
      },

    结果 

    updated

    特点:

    在数据驱动下导致的虚拟DOM重新渲染和打补丁之后调用,此时,组件DOM已经更新。只会在数据变更之后触发这个钩子函数。

    示例

      updated: function () {
        console.group('updated 更新完成状态===============》');
        console.log(document.getElementById("myUl").children[2].innerHTML);
        console.log(document.getElementById("myUl").children[3].innerHTML);
      }, 

    结果 

    beforeDestroy

    特点:

    实例销毁之前调用,此时实例还可用

    示例:

    (清除定时器 / 解绑js定义的事件)

    destroyed

    特点:

    实例销毁后调用,实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁,

    示例:

    (清除定时器 / 解绑js定义的事件)

    大家也可以看看:

    Vue都使用那么久了,还不了解它的生命周期吗了解Vue的生命周期vue组件的生命周期讲解

    2.keep-alive相关问题

    keep-alive是什么?

    keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 transition 相似,keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件链中。

    有什么用?

    主要用于保留组件状态或避免重新渲染;在组件切换过程中将状态保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性。

    参考:vue官网、 vue 使用keep-alive使用总结和进入缓存页需要再次更新数据

    有哪些属性

    • include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
    • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
    • max - 数字。最多可以缓存多少组件实例。

    生命周期执行顺序

    • 初次进入时:created > mounted > activated;退出后触发 deactivated
    • 再次进入:会触发 activated;事件挂载的方法等。
    使用  keep-alive  后遇到返回页面数据更新时怎么办呢?
    因为使用 keep-alive 的组件再次进入创建前/后、载入前/后,但会触发activated ,所以只执行一次的放在 mounted 中,组件每次进去执行的方法放在 activated 中。简单来说就是在activated  中去更新数据。

    注意啦注意啦  `````````````````防坑指南

    1. keep-alive 先匹配被包含组件的 name 字段,如果 name 不可用,则匹配当前组件 components 配置中的注册名称。
    2. keep-alive 不会在函数式组件中正常工作,因为它们没有缓存实例。
    3. 当匹配条件同时在 includeexclude 存在时,以 exclude 优先级最高(当前vue 2.4.2 version)。比如:包含于排除同时匹配到了组件A,那组件A不会被缓存。
    4. 包含在 keep-alive 中,但符合 exclude ,不会调用activateddeactivated
    参考: Vue中keep-alive的深入理解和使用

    3.虚拟DOM相关问题

    什么是虚拟DOM

    Virtual dom, 即虚拟DOM节点。它通过JS的Object对象模拟DOM中的节点,然后再通过特定的render方法将其渲染成真实的DOM节点。

    虚拟DOM实现原理是什么?

    1. 数据和模板相结合生成虚拟dom
    2. 虚拟dom转化成真是dom渲染到页面上
    3. 当数据发生改变时,新的数据和模板相结合会生成新的虚拟dom
    4. 新旧虚拟dom进行比对找差异
    5. 找到差异后根据差异改变dom
    6. 老的虚拟dom被清除,新的虚拟dom变成老的虚拟dom

    虚拟dom相比真实dom的优势在哪里?

    • 减少dom操作(虚拟dom可以将多次操作合并为一次操作。比如你添加1000个节点,传统方法是一个接一个的操作。虚拟dom借助dom diff可以把多余的操作步骤省略掉,比如你添加1000个节点,其实只有10个节点是新增的。)
    • 跨平台渲染(虚拟 DOM 本质上是 JavaScript 对象,⽽ DOM 与平台强相关,相⽐之下虚拟 DOM 可以进⾏更⽅便地跨平台操作,例如
      服务器渲染、weex 开发等等。)
    参考: 虚拟dom的原理与diff算法虚拟 DOM 是什么? 有什么优缺点?

    模板和虚拟dom的关系

    vue框架中有一个compile模块,它主要负责将模板转换为render函数,而render函数调用后将得到虚拟dom。

    参考:阐述一下对vue虚拟dom的理解

    加考点:什么是diff算法

    各种百度后小颖的理解是:在数据发生变化时对比新旧虚拟dom,更新试图的过程就叫diff算法。

    网上答案小颖觉得比较的是:diff的过程就是调用名为patch的函数,比较新旧节点,一边比较一边给真实的DOM打补丁。

    参考:详解vue的diff算法

    4.双向绑定原理

    通过Object.defineProperty() 方法来劫持(监听)各属性的 getter、setter,并在当监听的属性发生变动时通知订阅者Watcher,是否需要更新,若更新就会执行对应的更新函数。而Object.defineProperty 是有局限性的,他的拦截的 target 就是单纯的对象的key的值,所以当对象属性的删减,数组,数组长度的改变,它就没法进行劫持了,这时就需要调用 $set方法来更新数据。

    参考:vue的双向绑定原理与实现Vue数据双向绑定的原理是什么?记一次忏悔的前端面试经验(Vue 双向绑定原理)

    5.v-model原理

    1. v-bind绑定一个value属性
    2. v-on监听当前元素的input事件,当数据变化时,将值传递给value实时更新数据
      <input :value="val" @input="val = $event.target.value">

    参考:Vue自定义组件实现v-model指令

    6.父子组件生命周期钩子函数执行顺序

    加载渲染过程

    父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

    更新过程

    父beforeUpdate->子beforeUpdate->子updated->父updated

    销毁过程

    父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

    7.父组件可以监听到子组件的生命周期吗?

    可以

    使用$emit

    // 父组件代码:
    <child @created="doSomething" />
    
    // 子组件代码:
    created() {
        this.$emit('created')
    }
    

    参考:Vue中父组件能否监听子组件的生命周期?

    8.请谈谈vue-router路由模式有几种?及hash和history路由实现原理

    参考小颖上一篇文章: hash和history路由的区别 

    后面的等有时间再写

  • 相关阅读:
    3139:[HNOI2013]比赛
    3143: [Hnoi2013]游走
    目前游戏行业内部主要几款游戏引擎的技术对比
    6.使用AngularJS模板来创建视图
    css选择器(E[att^=”val”]序号选择器)
    5.把作用域实现为数据模型
    4.了解AngularJS模块和依赖注入
    3.创建基本的AngularJS应用
    2.AngularJS MVC
    1.AngularJS初探
  • 原文地址:https://www.cnblogs.com/yingzi1028/p/16337370.html
Copyright © 2020-2023  润新知