VUE面试题汇总(一)

22 篇文章 82 订阅

1. vue 中的性能优化

参考答案:

1)编码优化

  • 尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher
  • v-if和v-for不能连用
  • 如果需要使用v-for给每项元素绑定事件时使用事件代理
  • SPA 页面采用keep-alive缓存组件
  • 在更多的情况下,使用v-if替代v-show
  • key保证唯一
  • 使用路由懒加载、异步组件
  • 防抖、节流
  • 第三方模块按需导入
  • 长列表滚动到可视区域动态加载
  • 图片懒加载

2)用户体验优化

  • 骨架屏
  • PWA(渐进式WEB应用)
  • 还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。

3)SEO优化

  • 预渲染
  • 服务端渲染SSR

4)打包优化

  • 压缩代码;
  • Tree Shaking/Scope Hoisting;
  • 使用cdn加载第三方模块;
  • 多线程打包happypack;
  • splitChunks抽离公共文件;
  • sourceMap优化;

说明:优化是个大工程,会涉及很多方面

2. Vue 的实例生命周期

参考答案:
在这里插入图片描述

(1) beforeCreate 初始化实例后 数据观测和事件配置之前调用

(2) created 实例创建完成后调用

(3) beforeMount 挂载开始前被用

(4) mounted el 被新建 vm. $el 替换并挂在到实例上之后调用

(5) beforeUpdate 数据更新时调用

(6) updated 数据更改导致的 DOM 重新渲染后调用

(7) beforeDestory 实例被销毁前调用

(8) destroyed 实例销毁后调用

Vue2 与Vue3的生命周期对比

变量实例化(次数)
beforeCreate(组件创建之前)setup(组件创建之前)
created(组件创建完成)setup(组件创建完成)
beforeMount(组件挂载之前)onBeforeMount(组件挂载之前)
mounted(组件挂载完成)onMounted(组件挂载完成)
beforeUpdate(数据更新,虚拟DOM打补丁之前)onBeforeUpdate(数据更新,虚拟DOM打补丁之前)
updated(数据更新,虚拟DOM渲染完成)onUpdated(数据更新,虚拟DOM渲染完成)
beforeDestroy(组件销毁之前)onBeforeUnmount(组件销毁之前)
destroyed(组件销毁之后)onUnmounted(组件销毁之后)

3. Vue 的双向数据绑定的原理

参考答案:

VUE 实现双向数据绑定的原理就是利用了 Object. defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。

Vue3. 0 将用原生 Proxy 替换 Object. defineProperty

4. 为什么要替换 Object. defineProperty?(Proxy 相比于 defineProperty 的优势)

参考答案:

  1. 在 Vue 中,Object.defineProperty 无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。

  2. Object.defineProperty只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue 2.x里,是通过 递归 + 遍历 data 对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象是才是更好的选择。

而要取代它的Proxy有以下两个优点;

  • 可以劫持整个对象,并返回一个新对象
  • 有13种劫持操作

既然Proxy能解决以上两个问题,而且Proxy作为es6的新属性在vue2. x之前就有了,为什么vue2. x不使用Proxy呢?一个很重要的原因就是:

Proxy是es6提供的新特性,兼容性不好,最主要的是这个属性无法用polyfill来兼容

5. 什么是 Proxy?

参考答案:

  1. 含义:

Proxy 是 ES6 中新增的一个特性,翻译过来意思是"代理",用在这里表示由它来“代理”某些操作。 Proxy 让我们能够以简洁易懂的方式控制外部对对象的访问。其功能非常类似于设计模式中的代理模式。

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

使用 Proxy 的核心优点是可以交由它来处理一些非核心逻辑(如:读取或设置对象的某些属性前记录日志;设置对象的某些属性值前,需要验证;某些属性的访问控制等)。 从而可以让对象只需关注于核心逻辑,达到关注点分离,降低对象复杂度等目的。

  1. 基本用法:
let p = new Proxy(target, handler);

参数:

  • target 是用Proxy包装的被代理对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
  • handler 是一个对象,其声明了代理target 的一些操作,其属性是当执行一个操作时定义代理的行为的函数。
  • p 是代理后的对象。当外界每次对 p 进行操作时,就会执行 handler 对象上的一些方法。Proxy共有13种劫持操作,handler代理的一些常用的方法有如下几个:
get: 读取
set: 修改
has: 判断对象是否有该属性
construct: 构造函数
  1. 示例:

下面就用Proxy来定义一个对象的get和set,作为一个基础demo

 let obj = {};
 let handler = {
     get(target, property) {
         console.log( `${property} 被读取` );
         return property in target ? target[property] : 3;
     },
     set(target, property, value) {
         console.log( `${property} 被设置为 ${value}` );
         target[property] = value;
     }
 }

 let p = new Proxy(obj, handler);
 p.name = 'tom' //name 被设置为 tom
 p.age; //age 被读取 3

p 读取属性的值时,实际上执行的是 handler. get() :在控制台输出信息,并且读取被代理对象 obj 的属性。

p 设置属性值时,实际上执行的是 handler. set() :在控制台输出信息,并且设置被代理对象 obj 的属性的值。

以上介绍了Proxy基本用法,实际上这个属性还有许多内容,具体可参考Proxy文档

三. 基于Proxy来实现双向绑定

6. 为什么避免 v-if 和 v-for 用在一起

参考答案:

vue2.x 中v-for优先级高于v-if,vue3.x 相反。所以2.x 版本中在一个元素上同时使用 v-if 和 v-for 时,v-for 会优先作用,造成性能浪费;3.x 版本中 v-if 总是优先于 v-for 生效,导致v-if访问不了v-for中的变量。

解析:

一般我们在两种常见的情况下会倾向于这样做:

  • 为了过滤一个列表中的项目 (比如 v-for=“user in users” v-if=“user.isActive”)。在这种情形下,请将 users 替换为一个计算属性 (比如 activeUsers),让其返回过滤后的列表。

  • 为了避免渲染本应该被隐藏的列表 (比如 v-for=“user in users” v-if=“shouldShowUsers”)。这种情形下,请将 v-if 移动至容器元素上 (比如 ul、ol)。

当 Vue 处理指令时,v-for 比 v-if 具有更高的优先级,所以这个模板:

<ul>
  <li
    v-for="user in users"
    v-if="user.isActive"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

将会经过如下运算:

this.users.map(function (user) {
  if (user.isActive) {
    return user.name
  }
})

因此哪怕我们只渲染出一小部分用户的元素,也得在每次重渲染的时候遍历整个列表,不论活跃用户是否发生了变化。

通过将其更换为在如下的一个计算属性上遍历:

computed: {
  activeUsers: function () {
    return this.users.filter(function (user) {
      return user.isActive
    })
  }
}
<ul>
  <li
    v-for="user in activeUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

我们将会获得如下好处:

  • 过滤后的列表只会在 users 数组发生相关变化时才被重新运算,过滤更高效。
  • 使用 v-for=“user in activeUsers” 之后,我们在渲染的时候只遍历活跃用户,渲染更高效。
  • 解耦渲染层的逻辑,可维护性 (对逻辑的更改和扩展) 更强。

为了获得同样的好处,我们也可以把:

<ul>
  <li
    v-for="user in users"
    v-if="shouldShowUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

更新为:

<ul v-if="shouldShowUsers">
  <li
    v-for="user in users"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

通过将 v-if 移动到容器元素,我们不会再对列表中的每个用户检查 shouldShowUsers。取而代之的是,我们只检查它一次,且不会在 shouldShowUsers 为否的时候运算 v-for。

反例:

<ul>
  <li
    v-for="user in users"
    v-if="user.isActive"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

<ul>
  <li
    v-for="user in users"
    v-if="shouldShowUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

好例子

<ul>
  <li
    v-for="user in activeUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

<ul v-if="shouldShowUsers">
  <li
    v-for="user in users"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

7. 组件的设计原则

参考答案:

(1)页面上每个独立的可视/可交互区域视为一个组件(比如页面的头部,尾部,可复用的区块)
(2)每个组件对应一个工程目录,组件所需要的各种资源在这个目录下就近维护(组件的就近维护思想体现了前端的工程化思想,为前端开发提供了很好的分治策略,在vue.js中,通过.vue文件将组件依赖的模板,js,样式写在一个文件中)
(每个开发者清楚开发维护的功能单元,它的代码必然存在在对应的组件目录中,在该目录下,可以找到功能单元所有的内部逻辑)
(3)页面不过是组件的容器,组件可以嵌套自由组合成完整的页面

8. vue slot是做什么的?

参考答案:主要是让组件的可扩展性更强,简单点说就是,能够在组件内写其他内容

解析:

插槽

在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 slot 和 slot-scope 这两个目前已被废弃但未被移除且仍在文档中的 attribute。

插槽内容

Vue 实现了一套内容分发的 API,这套 API 的设计灵感源自 Web Components 规范草案,将 元素作为承载分发内容的出口。

它允许你像这样合成组件:

<navigation-link url="/profile">
  Your Profile
</navigation-link>

然后你在 的模板中可能会写为:

<a
  v-bind:href="url"
  class="nav-link"
>
  <slot></slot>
</a>
编译作用域

9. 对于 Vue 是一套渐进式框架的理解

参考答案:

渐进式代表的含义是:没有多做职责之外的事。

vue.js只提供了vue-cli生态中最核心的组件系统和双向数据绑定,像vuex、vue-router都属于围绕vue.js开发的库。

解析:

要使用Angular,必须接受以下东西:

1、必须使用它的模块机制。
2、必须使用它的依赖注入。
3、必须使用它的特殊形式定义组件(这一点每个视图框架都有,这是难以避免的)
所以Angular是带有比较强的排它性的,如果你的应用不是从头开始,而是要不断考虑是否跟其他东西集成,这些主张会带来一些困扰。

要使用React,你必须理解:

1、函数式编程的理念。
2、需要知道它的副作用。
3、什么是纯函数。
4、如何隔离、避免副作用。
5、它的侵入性看似没有Angular那么强,主要因为它是属于软性侵入的。

Vue与React、Angular的不同是,它是渐进的:
1、可以在原有的大系统的上面,把一两个组件改用它实现,就是当成jQuery来使用。
2、可以整个用它全家桶开发,当Angular来使用。
3、可以用它的视图,搭配你自己设计的整个下层使用。
4、可以在底层数据逻辑的地方用OO(Object–Oriented)面向对象和设计模式的那套理念。
5、可以函数式,它只是个轻量视图而已,只做了最核心的东西。

场景联想

场景 1:
维护一个老项目管理后台,日常就是提交各种表单了,这时候你可以把 vue 当成一个 js 库来使用,就用来收集 form 表单,和表单验证。

场景 2:
得到 boss 认可,后面整个页面的 dom 用 Vue 来管理,抽组件,列表用 v-for 来循环,用数据驱动 DOM 的变化

场景 3:
越来越受大家信赖,领导又找你了,让你去做一个移动端 webapp,直接上了 vue 全家桶!

场景 1-3 从最初的只因多看你一眼而用了前端 js 库,一直到最后的大型项目解决方案。

10. vue. js 的两个核心是什么?

参考答案:

数据驱动和组件化思想

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柠檬树上柠檬果柠檬树下你和我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值