vue面试题分享
【转载自】https://juejin.cn/post/6844904115886096391
1. SPA 单页面的理解
SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,避免页面的重新加载。
优点:
用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
基于上面一点,SPA 相对对服务器压力小;
前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
缺点:
初次加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载;
前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;
SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。
2.v-show 与 v-if 有何区别?
v-if 是真正的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;也是短路的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 “display” 属性进行切换。
所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。
3.computed 和 watch 的区别和运用场景?
computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;
需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
4.组件中 data 为什么是函数
组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。
而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。
5.Vue 生命周期?
- beforeCreate
在调用beforeCreate的时候, 仅仅表示Vue实例刚刚被创建出来
此时此刻还没有初始化好Vue实例中的数据和方法, 所以还不能访问Vue实例中保存的数据和方法 - created
在调用created的时候, 是我们最早能够访问Vue实例中保存的数据和方法的地方 - beforeMount
在调用beforeMount的时候, 表示Vue已经编译好了最终模板, 但是还没有将最终的模板渲染到界面上 - mounted
在调用mounted的时候, 表示Vue已经完成了模板的渲染, 我们已经可以拿到界面上渲染之后的内容了 - beforeUpdate
在调用beforeUpdate的时候, 表示Vue实例中保存的数据被修改了
只有保存的数据被修改了才会调用beforeUpdate, 否则不会调用
在调用beforeUpdate的时候, 数据已经更新了, 但是界面还没有更新 - updated
在调用updated的时候, 表示Vue实例中保存的数据被修改了, 并且界面也同步了修改的数据了
也就是说: 数据和界面都同步更新之后就会调用update - beforeDestroy
在调用beforeDestroy的时候, 表示当前组件即将被销毁了
只要组件不被销毁, 那么beforeDestroy就不会调用。beforeDestroy函数是我们最后能够访问到组件数据和方法的函数 - destroyed
在调用destroyed的时候, 表示当前组件已经被销毁了
只要组件不被销毁, 那么destroyed就不会调用。在这个生命周期方法中无法再去操作组件中数据和方法
6.组件间的通信
-
props
/$emit
在父组件中通过v-bind传递数据,在子组件中通过props接收数据
在父组件中通过 v-on 传递方法,在子组件的自定义方法中通过this.$emit('自定义接收名称');
触发传递过来的方法 -
$emit/$on
这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。// 1.定义一个空的Vue实例 var Event = new Vue(); // 2.传递数据 Event.$emit(事件名,数据); // 3.获取数据 Event.$on(事件名,data => {});
-
vuex
vuex 是 Vue 配套的 公共数据管理工具,我们可以将共享的数据保存到 vuex 中, 方便整个程序中的任何组件都可以获取和修改vuex中保存的公共数据
-
创建Vuex对象
const store = new Vuex.Store({ // 这里的state就相当于组件中的data, 就是专门用于保存共享数据的 state: { msg: "共享数据" } });
-
在祖先组件中添加 store 的 key 保存Vuex对象
只要祖先组件中保存了Vuex对象 , 那么祖先组件和所有的后代组件就可以使用Vuex中保存的共享数据了
store: store,
-
在使用Vuex中保存的共享数据的时候, 必须通过如下的格式来使用
<p>{{this.$store.state.msg}}</p>
-
-
作用域插槽
作用域插槽就是带数据的插槽, 就是让父组件在填充子组件插槽内容时也能使用子组件的数据
应用场景在于: 子组件提供数据, 父组件决定如何渲染- 在
slot
中通过v-bind:数据名称="数据名称"
方式暴露数据 - 在父组件中通过
<template slot-scope="作用域名称">
接收数据 - 在父组件的
<template></template>
中通过 作用域名称.数据名称 方式使用数据
在 Vue2.6.版本中,为作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。
它取代了slot-scope也就是说我们可以通过
v-slot
指令告诉Vue如何接收作用域插槽暴露的数据格式:
v-slot:插槽名称="作用域名称"
简写:#插槽名称="作用域名称"
- 在
7.双向绑定原理
mvvm 双向绑定,采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()
来劫持各个属性的 setter、getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
Vue主要通过以下4个步骤实现数据双向绑定:
1、实现一个数据监听器 Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
2、实现一个指令解析器 Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
3、实现一个订阅者 Watcher,作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
4、最后实现 MVVM 作为数据绑定的入口,整合监听器、解析器和订阅者
8.介绍nextTick()
定义:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
所以就衍生出了这个获取更新后的DOM的Vue方法。所以放在Vue.nextTick()回调函数中的执行的应该是会对DOM进行操作的 js代码;
理解:nextTick(),是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数
// 修改数据
vm.msg = 'Hello'
// DOM 还未更新
Vue.nextTick(function () {
// DOM 更新
})
9.在哪个生命周期内调用异步请求?
可以在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。
但是最常用的是在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有两个
优点:
1、能更快获取到服务端数据,减少页面 loading 时间;
2、放在 created 中有助于一致性,因为ssr 不支持 beforeMount 、mounted 钩子函数。
10.MVVM是什么?以及MVVM优点
mvvm是什么?
- MVVM是Model-View-ViewModel的简写
- 它本质上是MVC 的改进版
- MVVM(Model-View-ViewModel)框架的由来是MVP(Model-View-Presenter)模式与WPF结合的应用方式时发展演变过来的一种新型架构框架
优点:
- 低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变
- 可重用性:你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑
- 独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xml代码
- 可测试:界面素来是比较难于测试的,而现在测试可以针对ViewModel来写
11.什么是组件以及如何使用组件
组件就是把一个很大的界面拆分为多个小的界面, 每一个小的界面就是一个组件
将大界面拆分成小界面就是组件化
组件化的好处是可以简化Vue实例的代码,可以提高代码复用性
Vue的组件注册分为全局注册和局部注册
全局注册是在全局Vue对象的component属性中绑定定义好的模板
局部注册是在Vue实例的components属性中绑定定义好的模板
如果是.vue文件的组件则需要通过import导入到需要的组件中。