最全vue面试题+详解答案 (上)

1、MVC 和 MVVM 区别

MVC
MVC全名是 Model View Controller,时模型 - 视图 - 控制器的缩写,一种软件设计典范。

  • Model(模型):是用于处理应用程序数据逻辑部分。通常模型对象负责在数据库中存取数据。
  • View(视图):是应用程序中处理数据显示的本分。通常视图是依据模型数据创建的。
  • Controller(控制器):是应用程序处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
    在这里插入图片描述
    MVC的思想:一句话描述就是Controller负责将Model的数据用View显示出来,换句话说就是在Controller里面把Model的数据赋值给View。

MVVM

MVVM新增了VM类。

ViewModel层:做了两件事达到了数据的双向绑定,一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。 实现的方式时:数据绑定。二是将【视图】转化成【模型】,即将所看到的页面转换成后端的数据。实现的方式是:DOM事件监听。

在这里插入图片描述
MVVM与MVC最大的区别就是:实现了View和Model的自动同步,也就是当Model的属性改变时,我们不用再手动操作Dom元素来改变View的显示。 而是改变属性后该属性对应的View层显示会自动改变(对应Vue数据驱动的思想)
整体看来,MVVM比MVC精简很多,不仅简化了业务与界面的依赖,还解决了数据频繁更新的问题,不用再用选择器操作DOM元素。因为在MVVM中,View不知道Model的存在,Model和ViewModel也察觉不到View,这种低耦合模式提高代码的可重用性。
注意:Vue并没有完全遵循MVVM的思想,这一点官网自己也有声明。
在这里插入图片描述
那么问题来了,为什么官方要说Vue没有完全遵循MVVM思想呢?
严格的MVVVM要求View不能和Model直接通信,而Vue提供了$refs这个属性,让Model可以直接操作View,违反了这一规定,所以是Vue没有完全遵循MVVM。

2、为什么data是一个函数

组件的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一分新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。

3、Vue组件通讯有哪些方式

  1. props 和 e m i t 。 父 组 件 向 子 组 件 传 递 数 据 是 通 过 p r o p s 传 递 的 , 子 组 件 传 递 给 父 组 件 是 通 过 emit。父组件向子组件传递数据是通过props传递的,子组件传递给父组件是通过 emitpropsemit触发事件来做到的。
  2. $parent 和 $children 获取单签组件的父组件和当前组件的子组件。
  3. $attrs 和 l i s t e n e r s A − > B − > C 。 V u e 2.4 开 始 提 供 了 listeners A -> B -> C。Vue2.4开始提供了 listenersA>B>CVue2.4attrs和$listeners来解决这个问题。
  4. 父组件中通过 provide 来提供变量,然后在子组件中通过 inject 来注入变量。(官方不推荐在实际业务中适用,但是写组件库时很常用。)
  5. $refs 获取组件实例。
  6. envetBus 兄弟组件数据传递,这种情况下可以使用事件总线的方式。
  7. envetBus 兄弟组件数据传递,这种情况下可以使用事件总线的方式。

4、Vue的生命周期方法有哪些?一般在哪一步发送请求?

beforeCreate在实例初始化之后,数据观测(data observe)和 event/watcher 事件配置之前被调用。在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问。

created实例已经创建完成之后被调用。在这一步,实例已经完成以下的配置:数据观测(data observe ),属性和方法的运算,watch/event 事件回调。这里没有 e l , 如 果 非 要 想 与 D O M 进 行 交 互 , 可 以 通 过 v m . el,如果非要想与 DOM 进行交互,可以通过vm. elDOMvm.nextTick 来访问 DOM。

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

Mounted 在挂载完成后发生,在当前阶段,真实的 Dom 挂载完毕,数据完成双向绑定,可以访问到 Dom节点。

beforeUpdate 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁 (patch)之前。可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。

updated 发生在更新完成之后,当前阶段组件 Dom 已经完成更新。要注意的是避免在此期间更新数据,因为这个可能导致无限循环的更新,该钩子在服务器渲染期间不被调用。

beforeDestroy 实例销毁之前调用。在这一步,实力仍然完全可用。我们可以在这时进行 善后收尾工作,比如清除定时器。

destroy Vue实例销毁后调用。调用后,Vue实例指示的东西都会解绑定,所有的事件监听器会被移除,左右的子实例也会被销毁,该钩子在服务器端渲染不被调用。

activated keep-alive 专属,组件被激活时调用

deactivated keep-alive 专属,组件被销毁时调用

异步请求在哪一步发起?
可以在钩子函数 created、beforeMount、mounted 中进行异步请求,因为在这三个钩子函数中,data已经创建,可以将服务器端返回的数据进行赋值。

如果异步请求不需要依赖 DOM 推荐加载 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:

  • 能更快获取到服务端数据,减少页面loading时间;
  • ssr 不支持 beforeMount、mounted 钩子函数,所以放在 created 中有助于一致性。

5、v-if 和 v-show 的区别

v-if 在编译过程中会被转化成三元表达式,条件不满足时不渲染此节点。

v-show 会被编译成指令,条件不满足时控制样式将此节点隐藏(display:none)

使用场景

v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景。

v-show 适用于需要非常频繁切换条件的场景。

扩展补充:display:none 、 visibility:hidden 和 opacity:0 之间的区别?
三者公共点都是隐藏。不同点:

  1. 是否占据空间。

    display:none,隐藏之后不占位置;visibility:hidden、opacity:0,隐藏后任然占据位置。

  2. 子元素是否继承。

    display:none — 不会被子元素继承,父元素都不存在了,子元素也不会显示出来。
    visibility:hidden — 会被子元素继承,通过设置子元素 visibility:visible 来显示子元素。
    opacity:0 — 会被子元素继承,但是不能设置子元素 opacity:0 来先重新显示。

  3. 事件绑定。

    display:none 的元素都已经不存在了,因此无法触发他绑定的事件。
    visibility:hidden 不会触发他上面绑定的事件。
    opacity:0 元素上面绑定的事件时可以触发的。

  4. 过度动画。

    transition对于display是无效的。
    transition对于visibility是无效的。
    transition对于opacity是有效的。

6、说说 vue 内置指令

在这里插入图片描述

  • v-once - 定义它的元素或组件只渲染一次,包括元素或组件的所有节点,首次渲染后,不再随数据的变化重新渲染,将被视为静态内容。
  • v-cloak - 这个指令保持在元素上直到关联实例结束编译 – 解决初始化慢到页面闪动的最佳实践。
  • v-bind - 绑定属性,动态更新HTML元素上的属性。例如 v-bind:class。
  • v-on - 用于监听DOM事件。例如 v-on:click v-on:keyup
  • v-html - 赋值就是变量的innerHTML – 注意防止xss攻击
  • v-text - 更新元素的textContent
  • v-model - 1、在普通标签。变成value和input的语法糖,并且会处理拼音输入法的问题。2、再组件上。也是处理value和input语法糖。
  • v-if / v-else / v-else-if。可以配合template使用;在render函数里面就是三元表达式。
  • v-show - 使用指令来实现 – 最终会通过display来进行显示隐藏
  • v-for - 循环指令编译出来的结果是 -L 代表渲染列表。优先级比v-if高最好不要一起使用,尽量使用计算属性去解决。注意增加唯一key值,不要使用index作为key。
  • v-pre - 跳过这个元素以及子元素的编译过程,以此来加快整个项目的编译速度。

7、怎样理解 Vue 的单项数据流

数据总是从父组件传到子组件,子组件没有权利修改父组件传过来的数据,只能请求父组件对原始数据进行修改。这样会防止从子组件意外改变父组件的状态,从而导致你的应用的数据流向难以理解。

注意:在子组件直接用 v-model 绑定父组件传过来的 props 这样是不规范的写法,开发环境会报警告。

如果实在要改变父组件的 props 值可以再data里面定义一个变量,并用 prop 的值初始化它,之后用$emit 通知父组件去修改。

8、computed 和 watch 的区别和运用的场景。

computed 是计算属性,依赖其它属性计算值,并且 computed 的值有缓存,职友集当计算值变化才会返回内容,他可以设置getter和setter。

watch 监听到值的变化就会执行回调,在回调中可以进行一系列的操作。

计算属性一般用在模板渲染中,某个值是依赖其它响应对象甚至是计算属性而来;而侦听属性适用于观测某个值的变化去完成一段复杂的业务逻辑。

9、v-if 和 v-for 为什么不建议一起使用

v-for和v-if不要在同一标签中使用,因为解析时先解析v-for在解析v-if。如果遇到需要同时使用时可以考虑写成计算属性的方式。

10、Vue 2.0 响应式数据的原理

整体思路是数据劫持 + 观察者模式

对象内部通过 defineReactive 方法,使用 Object.defineProperty 将属性进行劫持(只会劫持已存在的属性),数组则是通过重写数组来实现。当页面使用对应属性时,每个属性都拥有自己的 dep 属性,存在它所依赖的 watcher (依赖收集)get,当属性变化后会通知自己对应的 watcher 去更新(派发更新)set。

  1. Object.defineProperty 数据劫持
  2. 使用 getter 收集依赖 ,setter 通知 watcher派发更新。
  3. watcher 发布订阅模式。

11、Vue 如何检测数组变化

数组考虑性能原因没有用 defineProperty 对数组的每一项进行拦截,而是选择对7种数组(push,shift,pop,splice,unshift,sort,reverse)方法进行重写(AOP 切片思想)。

所以在 Vue 中修改数组的索引和长度无法监控到。需要通过以上7种变异方法修改数组才会触发数组对应的watcher进行更新。

12、Vue3.0 用过吗?了解多少?

  • 响应式原理的改变 Vue3.x 使用 Proxy 取代 Vue2.x 版本的 Object.defineProperty。
  • 组件选项声明方式 Vue3.x 使用 Composition API setup是Vue3.x新增的一个选项,他是组件内使用Composition API 的入口。
  • 模板语法变化 slot 具名插槽语法,自定义指令v-model升级。
  • 其他方面的更改 Suspense支持Fragment(多个根节点)和 Protal(在dom其他部分渲染组件内容)组件,针对一些特殊的场景做了处理。基于 treeShaking 优化,提供了更多的内置功能。

13、Vue3.0 和 2.0 的响应式原理区别

Vue3.x 改用 Proxy 替代 Object.defineProperty。因为 Proxy 可以直接监听对象和数组的变化,并且有多达13种拦截方法。

Vue的父子组件生命周期钩子函数执行顺序:

  • 加载渲染过程
    父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted

  • 子组件更新过程
    父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated

  • 父组件更新过程
    父beforeUpdate -> 父updated

  • 销毁过程

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

15、虚拟DOM是什么?有什么优缺点?

由于在浏览器中操作DOM是很昂贵的。频繁操作DOM,会产生一定性能问题。这就是虚拟Dom的产生原因。Vue2的Virtual DOM 借鉴了开源库 snabbdom 的实现。Virtual DOM本质就是用一个原生的JS对象去描述一个DOM节点,是对真实DOM的一层抽象。
优点:

  1. 保证性能下限:框架的虚拟DOM需要适配任何上层API可能产生的操作,他的一些DOM操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的DOM操作性能要好很多,因此框架的虚拟DOM至少可以保证在你不需要手动优化的情况下,依然可以提供还不错的性能,既保证性能的下限。
  2. 无需手动操作DOM:我们不需手动去操作DOM,只需要写好 View-Model的 代码逻辑,框架会根据虚拟DOM和数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率。
  3. 跨平台:虚拟DOM本质上是JavaScript对象,而DOM与平台强相关,相比之下虚拟DOM可以进行更方便地跨平台操作,例如服务器端渲染、weex开发等等。

缺点:

  1. 无法进行极致优化:虽然虚拟DOM + 合理的优化,足以应对大部分应用的性能需要,但在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致优化。
  2. 首次渲染大量DOM时,由于多了一层DOM计算,会比innerHTML插入慢。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值