• 技术文章 >头条

    20+个Vue经典面试题(附源码级详解)

    青灯夜游青灯夜游2022-05-18 20:41:57转载232
    本篇文章给大家总结分享20+个Vue经典面试题(附源码级详解),带你梳理基础知识,增强Vue知识储备,值得收藏,快来看看吧!

    01-Vue组件之间通信方式有哪些

    vue是组件化开发框架,所以对于vue应用来说组件间的数据通信非常重要。 此题主要考查大家vue基本功,对于vue基础api运用熟练度。 另外一些边界知识如provide/inject/$attrs则提现了面试者的知识广度。


    组件传参的各种方式

    1.png


    思路分析:


    回答范例:

    1、组件通信常用方式有以下8种:

    注意vue3中废弃的几个API

    https://v3-migration.vuejs.org/breaking-changes/children.html

    https://v3-migration.vuejs.org/breaking-changes/listeners-removed.html

    https://v3-migration.vuejs.org/breaking-changes/events-api.html#overview


    2、根据组件之间关系讨论组件通信最为清晰有效


    02-v-if和v-for哪个优先级更高?

    分析:

    此题考查常识,文档中曾有详细说明v2|v3;也是一个很好的实践题目,项目中经常会遇到,能够看出面试者api熟悉程度和应用能力。


    思路分析:


    回答范例:


    知其所以然:

    做个测试,test.html两者同级时,渲染函数如下:

    ƒ anonymous(
    ) {
    with(this){return _c('div',{attrs:{"id":"app"}},_l((items),function(item){return (item.isActive)?_c('div',{key:item.id},[_v("\n      "+_s(item.name)+"\n    ")]):_e()}),0)}
    }

    做个测试,test-v3.html

    2.png


    源码中找答案

    v2:https://github1s.com/vuejs/vue/blob/HEAD/src/compiler/codegen/index.js#L65-L66

    v3:https://github1s.com/vuejs/core/blob/HEAD/packages/compiler-core/src/codegen.ts#L586-L587


    03-简述 Vue 的生命周期以及每个阶段做的事

    必问题目,考查vue基础知识。

    思路


    回答范例

    1、每个Vue组件实例被创建后都会经过一系列初始化步骤,比如,它需要数据观测,模板编译,挂载实例到dom上,以及数据变化时更新dom。这个过程中会运行叫做生命周期钩子的函数,以便用户在特定阶段有机会添加他们自己的代码。

    2、Vue生命周期总共可以分为8个阶段:创建前后, 载入前后, 更新前后, 销毁前后,以及一些特殊场景的生命周期。vue3中新增了三个用于调试和服务端渲染场景。

    生命周期v2生命周期v3描述
    beforeCreatebeforeCreate组件实例被创建之初
    createdcreated组件实例已经完全创建
    beforeMountbeforeMount组件挂载之前
    mountedmounted组件挂载到实例上去之后
    beforeUpdatebeforeUpdate组件数据发生变化,更新之前
    updatedupdated数据数据更新之后
    beforeDestroybeforeUnmount组件实例销毁之前
    destroyedunmounted组件实例销毁之后
    生命周期v2生命周期v3描述
    activatedactivatedkeep-alive 缓存的组件激活时
    deactivateddeactivatedkeep-alive 缓存的组件停用时调用
    errorCapturederrorCaptured捕获一个来自子孙组件的错误时被调用
    -renderTracked调试钩子,响应式依赖被收集时调用
    -renderTriggered调试钩子,响应式依赖被触发时调用
    -serverPrefetchssr only,组件实例在服务器上被渲染前调用

    3、Vue生命周期流程图:

    3.png

    4、结合实践:

    beforeCreate:通常用于插件开发中执行一些初始化任务

    created:组件初始化完毕,可以访问各种数据,获取接口数据等

    mounted:dom已创建,可用于获取访问数据和dom元素;访问子组件等。

    beforeUpdate:此时view层还未更新,可用于获取更新前各种状态

    updated:完成view层的更新,更新后,所有状态已是最新

    beforeunmount:实例被销毁前调用,可用于一些定时器或订阅的取消

    unmounted:销毁一个实例。可清理它与其它实例的连接,解绑它的全部指令及事件监听器


    可能的追问


    知其所以然

    vue3中生命周期的派发时刻:

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/componentOptions.ts#L554-L555

    vue2中声明周期的派发时刻:

    https://github1s.com/vuejs/vue/blob/HEAD/src/core/instance/init.js#L55-L56


    04-能说一说双向绑定使用和原理吗?

    题目分析:

    双向绑定是vue的特色之一,开发中必然会用到的知识点,然而此题还问了实现原理,升级为深度考查。


    思路分析:


    回答范例:


    可能的追问:


    知其所以然:

    测试代码,test.html

    观察输出的渲染函数:

    // <input type="text" v-model="foo">
    _c('input', { 
      directives: [{ name: "model", rawName: "v-model", value: (foo), expression: "foo" }], 
      attrs: { "type": "text" }, 
      domProps: { "value": (foo) }, 
      on: { 
        "input": function ($event) { 
          if ($event.target.composing) return; 
          foo = $event.target.value 
        } 
      } 
    })
    // <input type="checkbox" v-model="bar">
    _c('input', { 
      directives: [{ name: "model", rawName: "v-model", value: (bar), expression: "bar" }], 
      attrs: { "type": "checkbox" }, 
      domProps: { 
        "checked": Array.isArray(bar) ? _i(bar, null) > -1 : (bar) 
      }, 
      on: { 
        "change": function ($event) { 
          var $$a = bar, $$el = $event.target, $$c = $$el.checked ? (true) : (false); 
          if (Array.isArray($$a)) { 
            var $$v = null, $$i = _i($$a, $$v); 
            if ($$el.checked) { $$i < 0 && (bar = $$a.concat([$$v])) } 
            else { 
              $$i > -1 && (bar = $$a.slice(0, $$i).concat($$a.slice($$i + 1))) } 
          } else { 
            bar = $$c 
          } 
        } 
      } 
    })
    // <select v-model="baz">
    //     <option value="vue">vue</option>
    //     <option value="react">react</option>
    // </select>
    _c('select', { 
      directives: [{ name: "model", rawName: "v-model", value: (baz), expression: "baz" }], 
      on: { 
        "change": function ($event) { 
          var $$selectedVal = Array.prototype.filter.call(
            $event.target.options, 
            function (o) { return o.selected }
          ).map(
            function (o) { 
              var val = "_value" in o ? o._value : o.value; 
              return val 
            }
          ); 
          baz = $event.target.multiple ? $$selectedVal : $$selectedVal[0] 
        } 
      } 
    }, [
      _c('option', { attrs: { "value": "vue" } }, [_v("vue")]), _v(" "), 
      _c('option', { attrs: { "value": "react" } }, [_v("react")])
    ])

    05-Vue中如何扩展一个组件

    此题属于实践题,考察大家对vue常用api使用熟练度,答题时不仅要列出这些解决方案,同时最好说出他们异同。

    答题思路:


    回答范例:


    可能的追问

    Vue.extend方法你用过吗?它能用来做组件扩展吗?


    知其所以然

    mixins原理:

    slots原理:


    06-子组件可以直接改变父组件的数据么,说明原因

    分析

    这是一个实践知识点,组件化开发过程中有个单项数据流原则,不在子组件中修改父组件是个常识问题。

    参考文档:https://staging.vuejs.org/guide/components/props.html#one-way-data-flow


    思路


    回答范例


    07-Vue要做权限管理该怎么做?控制到按钮级别的权限怎么做?

    分析

    综合实践题目,实际开发中经常需要面临权限管理的需求,考查实际应用能力。

    权限管理一般需求是两个:页面权限和按钮权限,从这两个方面论述即可。

    4.png


    思路


    回答范例


    知其所以然

    路由守卫

    https://github1s.com/PanJiaChen/vue-element-admin/blob/HEAD/src/permission.js#L13-L14

    路由生成

    https://github1s.com/PanJiaChen/vue-element-admin/blob/HEAD/src/store/modules/permission.js#L50-L51

    动态追加路由

    https://github1s.com/PanJiaChen/vue-element-admin/blob/HEAD/src/permission.js#L43-L44


    可能的追问


    08 - 说一说你对vue响应式理解?

    分析

    这是一道必问题目,但能回答到位的比较少。如果只是看看一些网文,通常没什么底气,经不住面试官推敲,但像我们这样即看过源码还造过轮子的,回答这个问题就会比较有底气啦。

    答题思路:


    回答范例:


    知其所以然

    vue2响应式:

    vue3响应式:


    09 - 说说你对虚拟 DOM 的理解?

    分析

    现有框架几乎都引入了虚拟 DOM 来对真实 DOM 进行抽象,也就是现在大家所熟知的 VNode 和 VDOM,那么为什么需要引入虚拟 DOM 呢?围绕这个疑问来解答即可!

    思路


    回答范例

    5.png


    知其所以然

    vnode定义:

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/vnode.ts#L127-L128

    观察渲染函数:21-vdom/test-render-v3.html

    创建vnode:

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/vnode.ts#L291-L292

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/vnode.ts#L486-L487

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/apiCreateApp.ts#L283-L284


    mount:

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/renderer.ts#L1171-L1172

    调试mount过程:mountComponent

    21-vdom/test-render-v3.html


    10 - 你了解diff算法吗?

    分析

    必问题目,涉及vue更新原理,比较考查理解深度。

    6.png


    思路


    回答范例

    1、Vue中的diff算法称为patching算法,它由Snabbdom修改而来,虚拟DOM要想转化为真实DOM就需要通过patch方法转换。

    2、最初Vue1.x视图中每个依赖均有更新函数对应,可以做到精准更新,因此并不需要虚拟DOM和patching算法支持,但是这样粒度过细导致Vue1.x无法承载较大应用;Vue 2.x中为了降低Watcher粒度,每个组件只有一个Watcher与之对应,此时就需要引入patching算法才能精确找到发生变化的地方并高效更新。

    3、vue中diff执行的时刻是组件内响应式数据变更触发实例执行其更新函数时,更新函数会再次执行render函数获得最新的虚拟DOM,然后执行patch函数,并传入新旧两次虚拟DOM,通过比对两者找到变化的地方,最后将其转化为对应的DOM操作。

    4、patch过程是一个递归过程,遵循深度优先、同层比较的策略;以vue3的patch为例:

    5、vue3中引入的更新策略:编译期优化patchFlags、block等


    知其所以然

    patch关键代码

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/renderer.ts#L354-L355

    调试 test-v3.html


    11 - 你知道哪些vue3新特性

    分析

    官网列举的最值得注意的新特性:https://v3-migration.vuejs.org/

    7.png

    也就是下面这些:

    以上这些是api相关,另外还有很多框架特性也不能落掉。


    回答范例

    1、api层面Vue3新特性主要包括:Composition API、SFC Composition API语法糖、Teleport传送门、Fragments 片段、Emits选项、自定义渲染器、SFC CSS变量、Suspense

    2、另外,Vue3.0在框架层面也有很多亮眼的改进:


    知其所以然

    体验编译器优化

    reactive实现


    12 - 怎么定义动态路由?怎么获取传过来的动态参数?

    分析

    API题目,考查基础能力,不容有失,尽可能说的详细。

    思路


    回答范例


    可能的追问

    https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#响应路由参数的变化

    https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#捕获所有路由或-404-not-found-路由


    13-如果让你从零开始写一个vue路由,说说你的思路

    思路分析:

    首先思考vue路由要解决的问题:用户点击跳转链接内容切换,页面不刷新。


    回答范例:

    一个SPA应用的路由需要解决的问题是页面跳转内容改变同时不刷新,同时路由还需要以插件形式存在,所以:


    知其所以然:

    https://github1s.com/vuejs/router/blob/HEAD/src/router.ts#L355-L356

    https://github1s.com/vuejs/router/blob/HEAD/src/history/html5.ts#L314-L315

    RouterView

    https://github1s.com/vuejs/router/blob/HEAD/src/RouterLink.ts#L184-L185

    https://github1s.com/vuejs/router/blob/HEAD/src/RouterView.ts#L43-L44


    14-能说说key的作用吗?

    分析:

    这是一道特别常见的问题,主要考查大家对虚拟DOM和patch细节的掌握程度,能够反映面试者理解层次。

    思路分析:


    回答范例:


    知其所以然

    测试代码,test-v3.html

    上面案例重现的是以下过程

    8.png

    不使用key

    9.png


    如果使用key

    // 首次循环patch A
    A B C D E
    A B F C D E
    
    // 第2次循环patch B
    B C D E
    B F C D E
    
    // 第3次循环patch E
    C D E
    F C D E
    
    // 第4次循环patch D
    C D
    F C D
    
    // 第5次循环patch C
    C 
    F C
    
    // oldCh全部处理结束,newCh中剩下的F,创建F并插入到C前面

    源码中找答案:

    判断是否为相同节点

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/vnode.ts#L342-L343

    更新时的处理

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/renderer.ts#L1752-L1753


    不使用key

    10.png

    如果使用key

    // 首次循环patch A
    A B C D E
    A B F C D E
    
    // 第2次循环patch B
    B C D E
    B F C D E
    
    // 第3次循环patch E
    C D E
    F C D E
    
    // 第4次循环patch D
    C D
    F C D
    
    // 第5次循环patch C
    C 
    F C
    
    // oldCh全部处理结束,newCh中剩下的F,创建F并插入到C前面

    源码中找答案:

    判断是否为相同节点

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/vnode.ts#L342-L343

    更新时的处理

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/renderer.ts#L1752-L1753


    15-说说nextTick的使用和原理?

    分析

    这道题及考察使用,有考察原理,nextTick在开发过程中应用的也较少,原理上和vue异步更新有密切关系,对于面试者考查很有区分度,如果能够很好回答此题,对面试效果有极大帮助。

    答题思路


    回答范例:

    1、nextTick是等待下一次 DOM 更新刷新的工具方法。

    2、Vue有个异步更新策略,意思是如果数据变化,Vue不会立刻更新DOM,而是开启一个队列,把组件更新函数保存在队列中,在同一事件循环中发生的所有数据变更会异步的批量更新。这一策略导致我们对数据的修改不会立刻体现在DOM上,此时如果想要获取更新后的DOM状态,就需要使用nextTick。

    3、开发时,有两个场景我们会用到nextTick:

    4、nextTick签名如下:function nextTick(callback?: () => void): Promise<void>

    所以我们只需要在传入的回调函数中访问最新DOM状态即可,或者我们可以await nextTick()方法返回的Promise之后做这件事。

    5、在Vue内部,nextTick之所以能够让我们看到DOM更新后的结果,是因为我们传入的callback会被添加到队列刷新函数(flushSchedulerQueue)的后面,这样等队列内部的更新函数都执行完毕,所有DOM操作也就结束了,callback自然能够获取到最新的DOM值。


    知其所以然:

    组件更新函数入队:

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/renderer.ts#L1547-L1548

    入队函数:

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/scheduler.ts#L84-L85

    nextTick定义:

    https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/scheduler.ts#L58-L59


    16-watch和computed的区别以及选择?

    两个重要API,反应应聘者熟练程度。

    思路分析


    computed特点:具有响应式的返回值

    const count = ref(1)
    const plusOne = computed(() => count.value + 1)

    watch特点:侦测变化,执行回调

    const state = reactive({ count: 0 })
    watch(
      () => state.count,
      (count, prevCount) => {
        /* ... */
      }
    )

    回答范例


    可能追问


    知其所以然

    computed的实现

    ComputedRefImpl

    缓存性

    watch的实现


    17-说一下 Vue 子组件和父组件创建和挂载顺序

    这题考查大家对创建过程的理解程度。

    思路分析


    回答范例


    知其所以然

    观察beforeCreated和created钩子的处理

    观察beforeMount和mounted钩子的处理

    测试代码,test-v3.html


    18-怎么缓存当前的组件?缓存后怎么更新?

    缓存组件使用keep-alive组件,这是一个非常常见且有用的优化手段,vue3中keep-alive有比较大的更新,能说的点比较多。

    思路


    回答范例


    知其所以然

    KeepAlive定义

    缓存定义

    缓存组件

    获取缓存组件

    测试缓存特性,test-v3.html


    19-从0到1自己构架一个vue项目,说说有哪些步骤、哪些重要插件、目录结构你会怎么组织

    综合实践类题目,考查实战能力。没有什么绝对的正确答案,把平时工作的重点有条理的描述一下即可。

    思路


    回答范例



    20-实际工作中,你总结的vue最佳实践有哪些?

    看到这样的题目,可以用以下图片来回答:

    11.png


    思路

    查看vue官方文档:

    风格指南:https://vuejs.org/style-guide/

    性能:https://vuejs.org/guide/best-practices/performance.html#overview

    安全:https://vuejs.org/guide/best-practices/security.html

    访问性:https://vuejs.org/guide/best-practices/accessibility.html

    发布:https://vuejs.org/guide/best-practices/production-deployment.html


    回答范例

    我从编码风格、性能、安全等方面说几条:


    21 - 简单说一说你对vuex理解?

    12.png

    思路


    范例


    可能的追问


    22-说说从 template 到 render 处理过程

    分析

    问我们template到render过程,其实是问vue编译器工作原理。

    思路

    回答范例

    知其所以然

    vue3编译过程窥探:

    测试,test-v3.html

    可能的追问


    23-Vue实例挂载的过程中发生了什么?

    分析

    挂载过程完成了最重要的两件事:

    把这两件事说清楚即可!

    回答范例

    知其所以然

    可能的追问

    原文地址:https://juejin.cn/post/7097067108663558151

    作者:杨村长

    (学习视频分享:vue视频教程

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    专题推荐:Vue vue.js
    上一篇:12306抢票,极限并发带来的思考! 下一篇:520程序员专属浪漫表白方式!无法拒绝!
    千万级数据并发解决方案

    相关文章推荐

    • 9个杀手级的PHP项目,快来收藏使用!• 10个值得了解的 Chrome 插件,助你提高工作效率!• 深入探讨“高并发大流量”访问的解决思路和方案• 12306抢票,极限并发带来的思考!
    1/1

    PHP中文网