2019年Vue前端面试题核心考点解析

作者:霁月

时间:2026-10-23

浏览:67

本文汇总了2019年针对Vue技术栈的前端面试题,涵盖MVVM架构理解、Vue指令差异、响应式原理机制、组件通信及数据监控方法。同时深入探讨了Vue中对象属性添加、数组删除等常见陷阱,以及SPA首屏加载和网站整体性能优化的具体策略。

文章目录

毕业后我在合肥一家小型公司任职,由于缺乏资深导师和技术交流氛围,我只能独自探索技术路径。管理层往往只注重愿景而忽视实际发展,导致个人职业前景不明朗。因此,我决定辞职,在新年伊始前往杭州,那里的互联网企业数量远超合肥。

抵达杭州后的三天内,我参加了多家公司的面试,涵盖规模较小、初创及发展较好的企业。本文将整理近期的面试题目进行复盘,鉴于我的技术栈以Vue为主,大部分问题均围绕Vue开发展开。

谈谈你对MVVM开发模式的理解

MVVM架构包含Model、View和ViewModel三个核心部分。

Model层负责定义数据模型及业务逻辑。

View层负责UI视图的展示。

ViewModel负责监听Model中数据的变化并控制视图更新,同时处理用户交互操作。

Model与View之间没有直接关联,而是通过ViewModel建立联系。Model与ViewModel之间存在双向数据绑定:当Model数据改变时触发View刷新,View中用户交互导致的数据变化也会同步至Model。

该模式实现了Model与View的数据自动同步,开发者只需专注于数据维护,无需手动操作DOM。

Vue有哪些指令?

常见的指令包括v-html、v-show、v-if、v-for等。

v-if 和 v-show 有什么区别?

v-show仅通过切换display属性(block或none)控制元素显示,不销毁DOM节点;v-if则控制DOM节点的存在与否。若需频繁切换显示状态,使用v-show性能开销更小;若仅需一次性显示或隐藏,v-if更为合理。

简述Vue的响应式原理

Vue实例创建时,会遍历data选项中的属性,利用Object.defineProperty将其转换为getter/setter,并在内部追踪依赖。当属性被访问或修改时,会通知变化。

每个组件实例拥有对应的watcher程序实例,在组件渲染过程中将属性记录为依赖。当依赖项的setter被调用时,会通知watcher重新计算,从而触发关联组件的更新。

谈谈你对MVVM开发模式的理解

Vue中如何在组件内部实现一个双向数据绑定?

假设存在一个输入框组件,需实现用户输入时同步父组件页面中的数据。

具体思路为:父组件通过props向子组件传值,子组件通过$emit通知父组件修改相应的props值。展示了具体实现。


import Vue from 'vue'
const component = {
 props: ['value'],
 template: `
  <div>
   <input type="text" @input="handleInput" :value="value">
  </div>
 `,
 data () {
  return {
  }
 },
 methods: {
  handleInput (e) {
   this.$emit('input', e.target.value)
  }
 }
}
new Vue({
 components: {
  CompOne: component
 },
 el: '#root',
 template: `
  <div>
   <comp-one :value1="value" @input="value = arguments[0]"></comp-one>
  </div>
 `,
 data () {
  return {
   value: '123'
  }
 }
})

如和所示,输入数据时父子组件中的数据会同步改变。

谈谈你对MVVM开发模式的理解

谈谈你对MVVM开发模式的理解

在父组件中,我们执行了两项操作:一是向子组件传入props,二是监听input事件并同步自身的value属性。这两步操作可进一步精简,只需修改父组件代码:。


template: `
  <div>
   <!--<comp-one :value1="value" @input="value = arguments[0]"></comp-one>-->
   <comp-one v-model="value"></comp-one>
  </div>
 `

v-model实际上会自动完成上述两步操作。

Vue中如何监控某个属性值的变化?

例如需要监控data中obj.a的变化,Vue中监控对象属性变化的方法如下:。


watch: {
   obj: {
   handler (newValue, oldValue) {
    console.log('obj changed')
   },
   deep: true
  }
 }

deep属性表示深层遍历,但上述写法会监控obj的所有属性变化,并非我们所需。因此需进行如下修改:。


watch: {
  'obj.a': {
   handler (newName, oldName) {
    console.log('obj.a changed')
   }
  }
 }

另一种方法是通过computed实现,代码如下:。


computed: {
  a1 () {
   return this.obj.a
  }
}

利用计算属性的特性,当依赖改变时,会重新计算出新值。

Vue中给data中的对象属性添加一个新的属性时会发生什么,如何解决?

示例代码如下:。


<template>
 <div>
  <ul>
   <li v-for="value in obj" :key="value">
    {{value}}
   </li>
  </ul>
  <button @click="addObjB">添加obj.b</button>
 </div>
</template>
<script>
export default {
 data () {
  return {
   obj: {
    a: 'obj.a'
   }
  }
 },
 methods: {
  addObjB () {
   this.obj.b = 'obj.b'
   console.log(this.obj)
  }
 }
}
</script>
<style></style>

点击按钮后,显示obj.b已成功添加,但视图并未刷新。

谈谈你对MVVM开发模式的理解

谈谈你对MVVM开发模式的理解

原因在于Vue实例创建时obj.b尚未声明,未被转换为响应式属性,因此不会触发视图更新。此时需使用Vue的全局API $set():。


addObjB () {
   // this.obj.b = 'obj.b'
   this.$set(this.obj, 'b', 'obj.b')
   console.log(this.obj)
  }

$set()方法相当于手动将obj.b处理为响应式属性,此时视图也会随之改变:。

谈谈你对MVVM开发模式的理解

delete和Vue.delete删除数组的区别

delete仅将被删除的元素变为empty/undefined,其他元素的键值保持不变。

Vue.delete则直接删除数组元素,改变了数组的键值结构。


  var a=[1,2,3,4]
  var b=[1,2,3,4]
  delete a[1]
  console.log(a)
  this.$delete(b,1)
  console.log(b)

谈谈你对MVVM开发模式的理解

谈谈你对MVVM开发模式的理解

如何优化SPA应用的首屏加载速度慢的问题?

将公用的JS库通过script标签外部引入,减小app.bundel的大小,让浏览器并行下载资源文件,提高下载速度。

在配置路由时,页面和组件使用懒加载方式引入,进一步缩小app.bundel的体积,在调用某个组件时再加载对应的js文件。

添加首屏loading图,提升用户体验。

前端如何优化网站性能?

减少HTTP请求数量。

浏览器与服务器通信主要依赖HTTP,每次握手需花费大量时间。不同浏览器对资源文件并发请求数量有限,一旦达到上限,资源请求将处于等待状态,严重影响性能。因此,减少HTTP请求数量是优化网站性能的关键。

CSS Sprites(CSS精灵):将多张图片合并为一张图片以减少HTTP请求,可通过CSS background属性访问图片内容。此方案还能减少图片总字节数。

合并CSS和JS文件:利用grunt、gulp、webpack等工程化打包工具,在发布前将多个CSS或JS文件合并为一个文件。

采用lazyLoad(懒加载):控制网页内容在初始阶段无需加载,不发送请求,仅在用户操作真正需要时加载内容,从而控制网页资源的一次性请求数量。

控制资源文件加载优先级。

浏览器解析HTML内容时从上至下进行,遇到link或script标签会加载对应链接内容。为第一时间展示页面,需提前加载CSS,避免受JS加载影响。

通常做法是将CSS置于头部,JS置于底部。

利用浏览器缓存。

浏览器缓存将网络资源存储于本地,下次请求该资源时,若资源已存在则无需向服务器重新请求,直接从本地读取。

减少重排(Reflow)。

基本原理:重排是DOM变化影响元素几何属性(宽和高)时,浏览器重新计算几何属性,使渲染树中受影响部分失效,并验证DOM树上其他节点的visibility属性。频繁Reflow会导致CPU使用率急剧上升。

减少Reflow:若需在DOM操作时添加样式,尽量通过增加class属性实现,而非直接通过style操作样式。

减少DOM操作。

图标使用IconFont替换。

网页从输入网址到渲染完成经历了哪些过程?

大致可分为以下7步:

输入网址。

发送到DNS服务器,获取域名对应的web服务器IP地址。

与web服务器建立TCP连接。

浏览器向web服务器发送HTTP请求。

web服务器响应请求,返回指定URL的数据(或错误信息、重定向的新URL地址)。

浏览器下载web服务器返回的数据及解析HTML源文件。

生成DOM树,解析CSS和JS,渲染页面,直至显示完成。

jQuery获取的dom对象和原生的dom对象有何区别?

JS原生获取的DOM是一个对象,jQuery对象则是数组对象,即选择出的元素的数组集合,两者属于不同的对象类型,不等价。

原生DOM对象转jQuery对象:。


var box = document.getElementById('box');
var $box = $(box);

jQuery对象转原生DOM对象:。


var $box = $('#box');
var box = $box[0];

jQuery如何扩展自定义方法


(jQuery.fn.myMethod=function () {
    alert('myMethod');
})
// 或者:
(function ($) {
    $.fn.extend({
       myMethod : function () {
         alert('myMethod');
       }
    })
})(jQuery)

使用方式如下:。


$("#div").myMethod();

目前公司面试问题相对基础,但对于仅追求使用而不研究原理的开发者而言可能具有一定难度。因此,学习不仅需追求广度,更需注重深度。

当前前端领域存在海量的JS库、复杂的兼容性问题以及层出不穷的新知识,令人感到学习压力巨大。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章