关于 vue.js 的面试

Q:Vue3 今年发布了,请你说一下他们之间在相应式的实现上有什么区别?
A:Vue2 采用的是 defineProperty 去定义 get,set,而 Vue3 改用了 proxy。也代表着 vue 放弃了兼容 ie。

Q:像 Vue-Router,Vuex 他们都是作为 Vue 插件,请说一下他们分别都是如何在 vue 中生效的?
A:通过 vue 的插件系统,用 vue.mixin 混入到全局,在每个组件的生命周期的某个阶段注入组件实例。

Q:请你说一下 Vue 的设计架构。
A:Vue2 采用的是典型的混入式架构,类似于 express 和 jquery,各部分分模块开发,再通过一个 mixin 去混入到最终暴露到全局的类上。

Q:请说一下你这个项目中做的事情?
A:这个项目主体是一个 vue 项目,但是因为是 pc 端,为了 seo,我特意做了 ssr。然后这个项目有一套我和同事一起做的专门的组件库。在移动端,我们为了搭配 app,也做了移动混合方案。像在首页,因为数据巨大,我们采用了一些优化方案。利用本地缓存数据,对小图标进行了 base64 转码。

Q:什么是 MVVM 框架?它适用于哪些场景?
A:MVVM 框架是一个 Model-View-ViewModel 框架,其中 ViewModel 连接模型(Model) 和 视图 (View)。

在数据操作比较多的场景中,MVVM 框架更合适,有助于通过操作数据渲染页面。

Q:active-class 是哪个组件的属性?
A:它是 vue-router 模块的 router-link 组件的属性。

Q:如何定义 vue-router 的动态路由?
A:在静态路由名称前面添加冒号,例如设置 id 动态路由参数,为路由对象的 path 属性设置:/:id。

Q:如何获取传过来的动态参数?
A:在组件中,使用 $router 对象的 params.id 即 $route.params.id。

Q:vue-router 有哪几种导航钩子?
A:有 3 种。

第一种是全局导航钩子:router.beforeEach(to,from,next)。作用是跳转前进行判断拦截。

第二种是组件内的钩子。

第三种是单独路由独享组件。

Q:mint-ui 是什么?如何使用?
A:它是基于 vue.js 的前端组件库,用 npm 安装,然后通过 import 导入样式 和 JavaScript 代码。

vue.use(minUi) 用于实现全局引入,import { Toast } from 'mint-ui'用于在单个组件局部引入。

Q:v-model 是 什么?有什么作用?
A:v-model 是 Vue.js 中的一条指令,可以实现数据的双向绑定。

Q:vue.js 中标签如何绑定事件?
A:绑定事件有两种方式。

第一种,通过 v-on 指令,<input v-on:click = "doLog()"/>

第二种,通过 @ 语法糖,<input @click = "doLog()">

Q:vuex 是 什么?如何使用?在哪种功能场景中使用它?
A:vuex 是针对 vue.js 框架实现的状态管理系统。

为了使用 vuex,要引入 store,并注入 vue.js 组建中,在组件内部即可通过 $store 访问 store 对象。

使用场景包括:在单页面应用中,用于组件之间的通信,例如音乐播放,登录状态管理,加入购物车等。

Q:如何实现自定义指令?它有哪些钩子函数?还有哪些钩子函数参数?

A:自定义指令包含以下两种。

全局自定义指令:vue.js 对象提供了 directive 方法,可以用来自定义指令,directive 方法接受两个参数,一个是指令名称,另一个是函数。

局部自定义指令:通过组件的 directive 属性定义。

它有如下钩子函数:

bind:在指令第一次绑定到元素时调用。

inserted:在被绑定元素插入父节点时调用(vue2.0新增的)

update:在所在组件的 VNode 更新时调用。

componentUpdated:在指令所在组件的 VNode 及其子 VNode 全部更新后调用(Vue2.0 新增的)。

unbind:只调用一次,在指令与元素解除绑定时调用。

钩子函数的参数如下。

el:指令所绑定的元素

binding:指令对象

vnode:虚拟节点

oldVnode:上一个虚拟节点

Q:至少说出 vue.js 中 4 种指令和它们的用法。

A:相关指令及其用法如下:

v-if:判断对象是否隐藏

v-for:循环渲染

v-bind:绑定一个属性

v-model:实现数据双向绑定

Q:vue-router 是什么?它有哪些组件?

A:它是 vue.js 的路由插件。组件包括 router-link 和 router-view

Q:导航钩子有哪些?它们有哪些参数?

A:导航钩子又称为导航守卫,又分为全局钩子,单个路由独享钩子和组件级钩子。

全局钩子有 beforeEach、beforeResolve(vue2.5.0新增)、afterEach。

单个路由独享钩子有 beforeEnter

组件级钩子有 beforeRouteEnter、beforeRouteUpdate(vue2.2 新增的)、beforeRouteLeave

它们有以下参数。

to:即将要进入的目标路由对象

from:当前导航正要离开的路由

next:一定要用这个函数才能到达下一个路由,如果不用就会遭到拦截

Q:Vue.js 的双向数据绑定原理是什么?

A:vue.js 采用 ES5 提供的属性特性功能,结合发布者-订阅者模式,通过 Object.defineProperty() 为各个属性定义 get、set 特性方法,

在数据发送改变时给订阅者发布消息,触发响应的监听回调。

具体步骤如下。

(1)对需要观察的数据对象进行递归遍历,包括子属性对象的属性,设置 set 和 get 特性方法。当给这个对象的某个值赋值时,

会触发绑定的 set 特性方法,于是就能监听到数据变化。

(2)用 compile 解析模板指令,将模板中的变量替换成数据。然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,

添加监听数据的订阅者,一旦数据有变动,就会收到通知,并更新视图。

(3)Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,主要功能如下。

在自身实例化时向属性订阅器(dep)里面添加自己

自身必须是一个 update() 方法

在 dep.notice() 发布通知时,能调用自身的 update() 方法,并触发 Compile 中绑定的回调函数

(4)MVVM 是数据绑定的入口,整合了 Observer、Compile 和 Watcher 三者,通过 Observer 来监听自己的 model 数据变化,

通过 Compile 来解析编译模板指令,最终利用 Watcher 搭建 Observer 和 Compile 之间的通信桥梁,达到数据变化通知视图更新的效果。利用视图交互,变化更新数据 model 变更的双向绑定效果。

Q:请详细说明你对 vue.js 生命周期的理解

A:总共分为 8 个阶段,分别是 beforeCreate、Created、beforeMount、mounted、beforeUpdate、updated、beforeDestroyed、destroyed。

beforeCreate:在实例初始化之后,数据观测者(data observer) 和 event/watcher 事件配置之前调用。

created:在实例创建完成后立即调用。在这一步,实例已完成以下配置:数据观测者、属性和方法的运算,watch/event 事件回调,然而,挂载阶段还没开始,$el 属性目前不可见。

beforeMount:在挂载开始之前调用,相关的 render 函数首次调用。

mounted:el 被新创建的 vm.$el 替代,并且在挂载到实例上之后再调用该钩子。如果 root 实例挂载了 一个文档内元素,当调用mounted 时 vm.$el 也在文档内。

beforeUpdate:在数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。

updated:由于数据更新导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

beforeDestroy:在实例销毁之前调用。在这一步,实例仍然完全可用。

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

当使用组件的 keep-alive 功能时,增加以下两个周期。

activated 在 keep-alive 组件激活时调用

deactivated 在 keep-alive 组件停用时调用

vue 2.5.0 版本新增了一个周期钩子:ErrorCaptured,当捕获一个来自子孙组件的错误时调用。

Q:请描述封装 Vue 组件的作用过程

A:组件可以提升整个项目的开发效率,能够把页面抽象成多个相对独立的模块,解决了传统项目开发中效率低、难维护、复用性等问题。

使用 vue.extend 方法创建一个组件,使用 Vue.component 方法注册组件,子组件需要数据,可以在 props 中接收数据,而子组件修改好数据后,若想把数据传递给父组件,可以采用 emit 方法。

Q:你是怎么认识 vuex 的?

A:vuex 可以理解为一种开发模式或框架。它是对 vue.js 框架数据层面的扩展,通过状态(数据源)集中管理驱动组件的变化,应用的状态集中放在 store 中。改变状态的方式是提交 mutations,这是个同步的事务,异步逻辑应该封装在 action 中。

Q:vue-loader 是什么?它的用途有哪些?

A: 它是解析 .vue 文件的一个加载器,可以将 template/js/style 转换成 JavaScript 模块。用途是通过 vue-loader,JavaScript 可以写 EMAScript 6 语法,style 样式可以应用 scss 和 less,template 可以添加 jade 语法等。

Q:请说出 vue.cli 项目的 src 目录中每个文件夹的用法。

A:assets 文件夹存放静态资源,components 存放组件,router 定义路由相关的配置;view 是视图;app.vue 是一个应用主组件;main.js 是入口文件。

Q:在 vue.cli 中怎样使用自定义组件?在使用过程中你遇到过哪些问题?

A:具体步骤如下。

(1)在 components 目录中新增组件文件,脚本一定要导出暴露的接口。

(2)导入需要用到的页面(组件)。

(3)将导入的组件注入 Vue.js 的子组件的 components 属性中。

(4)在 template 的视图中使用自定义组件。

Q:谈谈你对 Vue.js 的 template 编译的理解

A:简而言之,就是首先转换成 AST(Abstract Syntax Tree,抽象语法树),即将源代码语法结构抽象成树状表现形式,然后通过 render 函数进行渲染,并返回 VNode(vue.js 的虚拟 DOM节点)。

详细步骤如下。

(1)通过 compile 编译器把 template 编译成 AST,compile 是 createCompiler 的返回值,createCompiler 用来创建编译器。另外,compile 还负责合并 option。

(2)AST 会经过 generate(将 AST 转化成 render function 字符串的过程)得到 render 函数,render 的返回值是 VNode,VNode是 Vue.js的虚拟 DOM节点,里面有标签名、子节点、文本等。

Q:说一下 Vue.js 中的 MVVM模式

A:MVVM 模式即 Model-View-ViewModel 模式。

Vue.js 是通过数据驱动的,vue.js 实例化对象将 DOM 和数据进行绑定。一旦绑定,DOM 和数据将保持同步,每当数据发生变化,DOM 也会随着变化。

ViewModel 是 Vue.js 的核心,它是 Vue.js 的一个实例。Vue.js 会针对某个 HTML 元素进行实例化,这个 HTML 元素可以是 body,也可以是某个 CSS 选择器所指代的元素。DOM Listeners 和 Data Bindings 是实现双向绑定的关键。DOM Listeners 监听页面所有 View 层中的 DOM 元素,当发生变化时,Model 层的数据随之变化。Data bindings 会监听 Model 层的数据,当数据发生变化时,View 层的 DOM 元素也随之变化。

Q:v-show 指令 和 v-if 指令的区别是什么?

A:v-show 与 v-if 都是条件渲染指令。不同的是,无论 v-show 的值为 true 或 false,元素都会存在于 HTML 页面中;而只有当 v-if 的值为 true 时,元素才会存在于 HTML 页面中。v-show 指令是通过修改元素的 style 属性值实现的。

Q:如何让 CSS 只在当前组件中起作用?

A:在每个 vue.js 组建中都可以定义各自的 CSS、JavaScript 代码。如果希望组件内写的 CSS 只对当前组件起作用,只需要在 style 标签中 添加 scoped 属性,即<style scoped></style>

Q:如何创建 Vue.js 组件?

A:在 Vue.js 中,组件要先注册,然后才能使用。具体代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!-- 应用程序 -->
<div id = "app">
<ickt></ickt>
</div>

<!-- 模板 -->
<template id = "demo">
<!-- 模板元素要有同一个根元素 -->
<div>
<h1>
{{msg}}
</h1>
</div>
</template>
<script type="text/javascript">
// 定义组件类
var Ickt = Vue.extend({
template: "#demo",
data: function(){
return {
msg: '爱创课堂'
}
}
})

// 注册组件
Vue.component('ickt',Ickt)
// 定义 vue 实例化对象
var app = new Vue({
el: "#app",
data: {}
})
</script>

Q:如何实现路由嵌套?如何进行页面跳转?

A:路由嵌套会将其他组件渲染到该组件内,而不是使整个页面跳转到 router-view 定义组件渲染的位置,要进行页面跳转。就要将页面渲染到根组件内,可做如下配置。

1
2
3
4
5
new Vue({
el: #icketang,
router: router,
template: "<rooter-view></rooter-view>"
})

首先,实例化根组件,在根组件中定义组件渲染容器,然后挂载路由,当切换路由时,将会切换整个页面。

Q:ref 属性有什么作用?

A:有时候,为了在组件内部可以直接访问组件内部的一些元素,可以定义该属性。此时可以在组件内部通过 this.$refs 属性,更快捷地访问设置 ref 属性的元素。这是一个原生的 DOM 元素,要使用原生 DOM API 操作它们,例如一下代码。

1
2
3
4
5
6
7
8
<div id="ickt">
<span ref="msg">爱创课堂</span>
<span ref="otherMsg">专业前端技术培学校</span>
</div>
app.$refs.msg.textContent // 爱创课堂
app.$refs.otherMsg.textContent // 专业前端技术培训学校

在 vue2.0中 ref 属性替代了 1.0 版本中 v-el 指令的功能

Q:Vue.js 是什么?

A:vue.js 是一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue.js 采用自下而上增量开发的设计、vue.js 的核心库只关注视图层,并且容易学习,易于与其他库或已有项目整合。另外,Vue.js 完全有能力驱动采用单文件组件以及 Vue.js 生态系统支持的库开发的复杂单页应用。

Vue.js 的目标是通过尽可能简单的 API 实现响应式的数据绑定和组件开发。

Q:描述 Vue.js 的一些特性

A:Vue.js 有以下特性

(1)MVVM 模式

数据模型(Model)发生改变,视图(View)监听到变化,也同步改变;视图(View)发生改变,数据模型(Model)监听到改变,也同步改变。

使用 MVVM 模式有几大好处。

  • 低耦合度,视图可以独立于模型变化和修改,一个 ViewModel 可以绑定到不同的视图上,当视图变化时模型可以不变,当模型变化时视图也可以不变。
  • 可重用性,可以把一些视图的逻辑放在 ViewModel 里面,让很多视图复用这段视图逻辑。
  • 独立开发,开发人员可以专注于业务逻辑和数据的开发,设计人员可以专注于视图的设计
  • 可测试性,可以针对 ViewModel 来对视图进行测试。

(2)组件化开发。

(3)指令系统

(4)Vue2.0 开始支持虚拟 DOM

但在 Vue 1.0 中,操作的是真实的 DOM 元素而不是虚拟的 DOM,虚拟 DOM 可以提升页面的渲染性能。

Q:描述 Vue.js 的特点

A:Vue.js 有以下特点。

  • 简洁:页面由 HTML 模板 + JSON数据 + vue.js实例化对象组成
  • 数据驱动:自动计算属性和追踪依赖的模板表达式
  • 组件化:用可复用、解耦的组件来构造页面
  • 轻量:代码量小、不依赖其他库
  • 快速:精确而有效地批量实现 DOM 更新
  • 易获取:可以通过 npm 、bower等多种方式安装,很容易融入。

Q:说说你对 SPA 单页面的理解,它的优缺点分别是什么?

A:SPA(single-page application)仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转,取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,避免页面的重新加载。

优点:

用户体验好、快、内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;

基于上面一点,SPA 相对对服务器压力小;

前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理

缺点:

初次加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载;

前进后退路由管理:由于单页应用在一个页面中显示所有内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理

SEO难度较大:由于所有的内容都在一个页面中动态替换显示,所以在SEO 上其有着天然的弱势。

以上是我对下列视频及文章的归纳和总结。


《前端程序员面试宝典—张容铭》

Vue - 前端面试之道

30 道 Vue 面试题

作者

Fallen-down

发布于

2020-12-05

更新于

2021-08-06

许可协议

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

评论

You forgot to set the shortname for Disqus. Please set it in _config.yml.
You need to set client_id and slot_id to show this AD unit. Please set it in _config.yml.