vue 面试题 + 答案,2021 前端面试
vue 视频教程系列:
Vue3+ElementPlus+Koa2 全栈开发后盾零碎
试看:点击观看
残缺课程:点击查看
Vue3.0 高阶实战:开发高质量音乐 Web app
试看:点击观看
残缺课程:点击查看
VUE 全面教学 +VUE 开源我的项目超级实战:
试看:点击观看
残缺课程:点击查看
最新 Vue.JS 教程疾速入门到我的项目实战(Vue3/VueJS 技术详解)
试看:点击观看
残缺课程:点击查看
最新最全前端毕设我的项目(小程序 +VUE+Noed+React+uni app+Express+Mongodb)
试看:点击观看
残缺课程:点击查看
MVC 和 MVVM 区别
MVC
MVC 全名是 Model View Controller,是模型 (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 思维呢?
- 严格的 MVVM 要求 View 不能和 Model 间接通信,而 Vue 提供了 $refs 这个属性,让 Model 能够间接操作 View,违反了这一规定,所以说 Vue 没有齐全遵循 MVVM。
vue 是如何实现响应式数据的呢?(响应式数据原理)
Vue2: Object.defineProperty
从新定义 data
中所有的属性, Object.defineProperty
能够使数据的获取与设置减少一个拦挡的性能,拦挡属性的获取,进行依赖收集。拦挡属性的更新操作,进行告诉。
具体的过程:首先 Vue 应用 initData
初始化用户传入的参数,而后应用 new Observer
对数据进行观测,如果数据是一个对象类型就会调用 this.walk(value)
对对象进行解决,外部应用 defineeReactive
循环对象属性定义响应式变动,外围就是应用 Object.defineProperty
从新定义数据。
那 vue 中是如何检测数组变动的呢?
数组就是应用 object.defineProperty
从新定义数组的每一项,那能引起数组变动的办法咱们都是晓得的, pop
、 push
、 shift
、 unshift
、 splice
、 sort
、 reverse
这七种,只有这些办法执行改了数组内容,我就更新内容就好了,是不是很好了解。
- 是用来函数劫持的形式,重写了数组办法,具体呢就是更改了数组的原型,更改成本人的,用户调数组的一些办法的时候,走的就是本人的办法,而后告诉视图去更新。
- 数组里每一项可能是对象,那么我就是会对数组的每一项进行观测,(且只有数组里的对象能力进行观测,观测过的也不会进行观测)
vue3:改用 proxy
,可间接监听对象数组的变动。
vue 的长处
轻量级框架:只关注视图层,是一个构建数据的视图汇合,大小只有几十 kb;
简略易学:国人开发,中文文档,不存在语言障碍,易于了解和学习;
双向数据绑定:保留了 angular 的特点,在数据操作方面更为简略;
组件化:保留了 react 的长处,实现了 html 的封装和重用,在构建单页面利用方面有着独特的劣势;
视图,数据,构造拆散:使数据的更改更为简略,不须要进行逻辑代码的批改,只须要操作数据就能实现相干操作;
虚构 DOM:dom 操作是十分消耗性能的,不再应用原生的 dom 操作节点,极大解放 dom 操作,但具体操作的还是 dom 不过是换了另一种形式;
运行速度更快: 相比拟与 react 而言,同样是操作虚构 dom,就性能而言,vue 存在很大的劣势。
为什么 vue 组件中 data 必须是一个函数?
对象为援用类型,当复用组件时,因为数据对象都指向同一个 data 对象,当在一个组件中批改 data 时,其余重用的组件中的 data 会同时被批改;而应用返回对象的函数,因为每次返回的都是一个新对象(Object 的实例),援用地址不同,则不会呈现这个问题。
v-if 和 v-show 的区别
v-if 在编译过程中会被转化成三元表达式, 条件不满足时不渲染此节点。
v-show 会被编译成指令,条件不满足时管制款式将对应节点暗藏(display:none)
为什么 Vue 采纳异步渲染呢?
Vue
是组件级更新,如果不采纳异步更新,那么每次更新数据都会对以后组件进行从新渲染,所以为了性能, Vue
会在本轮数据更新后,在异步更新视图。核心思想 nextTick
。
dep.notify()
告诉 watcher 进行更新, subs[i].update
顺次调用 watcher 的 update
, queueWatcher
将 watcher 去重放入队列,nextTick( flushSchedulerQueue
)在下一 tick 中刷新 watcher 队列(异步)。
父子组件生命周期调用程序(简略)
渲染程序:先父后子,实现程序:先子后父
更新程序:父更新导致子更新,子更新实现后父
销毁程序:先父后子,实现程序:先子后父
用 VNode 来形容一个 DOM 构造
虚构节点就是用一个对象来形容一个实在的 DOM 元素。首先将 template
(实在 DOM)先转成 ast
, ast
树通过 codegen
生成 render
函数, render
函数里的 _c
办法将它转为虚构 dom
diff 算法
工夫复杂度: 个树的齐全 diff
算法是一个工夫复杂度为 O(n*3)
,vue 进行优化转化成 O(n)
。
了解:
-
最小量更新,
key
很重要。这个能够是这个节点的惟一标识,通知diff
算法,在更改前后它们是同一个 DOM 节点- 扩大
v-for
为什么要有key
,没有key
会暴力复用,举例子的话轻易说一个比方挪动节点或者减少节点(批改 DOM),加key
只会挪动缩小操作 DOM。
- 扩大
- 只有是同一个虚构节点才会进行精细化比拟,否则就是暴力删除旧的,插入新的。
- 只进行同层比拟,不会进行跨层比拟。
diff 算法的优化策略:四种命中查找,四个指针
- 旧前与新前(先比结尾,后插入和删除节点的这种状况)
- 旧后与新后(比结尾,前插入或删除的状况)
- 旧前与新后(头与尾比,此种产生了,波及挪动节点,那么新前指向的节点,挪动到旧后之后)
- 旧后与新前(尾与头比,此种产生了,波及挪动节点,那么新前指向的节点,挪动到旧前之前)
v-for 为什么要加 key
如果不应用 key,Vue 会应用一种最大限度缩小动静元素并且尽可能的尝试就地批改 / 复用雷同类型元素的算法。key 是为 Vue 中 vnode 的惟一标记,通过这个 key,咱们的 diff 操作能够更精确、更疾速
更精确:因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 比照中能够防止就地复用的状况。所以会更加精确。
更疾速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历形式更快
vue-router 路由钩子函数是什么 执行程序是什么
路由钩子的执行流程, 钩子函数品种有: 全局守卫、路由守卫、组件守卫
残缺的导航解析流程:
- 导航被触发。
- 在失活的组件里调用 beforeRouteLeave 守卫。
- 调用全局的 beforeEach 守卫。
- 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
- 在路由配置里调用 beforeEnter。
- 解析异步路由组件。
- 在被激活的组件里调用 beforeRouteEnter。
- 调用全局的 beforeResolve 守卫 (2.5+)。
- 导航被确认。
- 调用全局的 afterEach 钩子。
- 触发 DOM 更新。
- 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创立好的组件实例会作为回调函数的参数传入。
谈一下对 vuex 的集体了解
vuex 是专门为 vue 提供的全局状态管理系统,用于多个组件中数据共享、数据缓存等。(无奈长久化、外部外围原理是通过发明一个全局实例 new Vue)
次要包含以下几个模块:
- State:定义了利用状态的数据结构,能够在这里设置默认的初始状态。
- Getter:容许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到部分计算属性。
- Mutation:是惟一更改 store 中状态的办法,且必须是同步函数。
- Action:用于提交 mutation,而不是间接变更状态,能够蕴含任意异步操作。
- Module:容许将繁多的 Store 拆分为多个 store 且同时保留在繁多的状态树中。
keep-alive 应用场景和原理
keep-alive 是 Vue 内置的一个组件,能够实现组件缓存,当组件切换时不会对以后组件进行卸载。
- 罕用的两个属性 include/exclude,容许组件有条件的进行缓存。
- 两个生命周期 activated/deactivated,用来得悉以后组件是否处于沉闷状态。
- keep-alive 的中还使用了 LRU(最近起码应用) 算法,抉择最近最久未应用的组件予以淘汰。
Vue.extend 作用和原理
官网解释:Vue.extend 应用根底 Vue 结构器,创立一个“子类”。参数是一个蕴含组件选项的对象。
其实就是一个子类结构器 是 Vue 组件的外围 api 实现思路就是应用原型继承的办法返回了 Vue 的子类 并且利用 mergeOptions 把传入组件的 options 和父类的 options 进行了合并
Vue 组件如何通信?
Vue 组件通信的办法如下:
props/$emit+v-on
: 通过 props 将数据自上而下传递,而通过 $emit 和 v -on 来向上传递信息。- EventBus: 通过 EventBus 进行信息的公布与订阅
- vuex: 是全局数据管理库,能够通过 vuex 治理全局的数据流
$attrs/$listeners
: Vue2.4 中退出的$attrs/$listeners
能够进行跨级的组件通信- provide/inject:以容许一个先人组件向其所有子孙后代注入一个依赖,不管组件档次有多深,并在起上下游关系成立的工夫里始终失效,这成为了跨组件通信的根底
还有一些用 solt 插槽或者 ref 实例进行通信的,应用场景过于无限就不赘述了。
computed 和 watch 有什么区别?
computed:
computed
是计算属性, 也就是计算值, 它更多用于计算值的场景computed
具备缓存性,computed 的值在 getter 执行后是会缓存的,只有在它依赖的属性值扭转之后,下一次获取 computed 的值时才会从新调用对应的 getter 来计算computed
实用于计算比拟耗费性能的计算场景
watch:
- 更多的是「察看」的作用, 相似于某些数据的监听回调, 用于察看
props
$emit
或者本组件的值, 当数据变动时来执行回调进行后续操作 - 无缓存性,页面从新渲染时值不变动也会执行
小结:
- 当咱们要进行数值计算, 而且依赖于其余数据,那么把这个数据设计为 computed
- 如果你须要在某个数据变动时做一些事件,应用 watch 来察看这个数据变动
虚构 DOM 的优劣如何?
长处:
- 保障性能上限: 虚构 DOM 能够通过 diff 找出最小差别, 而后批量进行 patch, 这种操作尽管比不上手动优化, 然而比起粗犷的 DOM 操作性能要好很多, 因而虚构 DOM 能够保障性能上限
- 无需手动操作 DOM: 虚构 DOM 的 diff 和 patch 都是在一次更新中主动进行的, 咱们无需手动操作 DOM, 极大进步开发效率
- 跨平台: 虚构 DOM 实质上是 JavaScript 对象, 而 DOM 与平台强相干, 相比之下虚构 DOM 能够进行更不便地跨平台操作, 例如服务器渲染、挪动端开发等等
毛病:
- 无奈进行极致优化: 在一些性能要求极高的利用中虚构 DOM 无奈进行针对性的极致优化, 比方 VScode 采纳间接手动操作 DOM 的形式进行极其的性能优化
虚构 DOM 实现原理?
- 虚构 DOM 实质上是 JavaScript 对象, 是对实在 DOM 的形象
- 状态变更时,记录新树和旧树的差别
- 最初把差别更新到真正的 dom 中
Vue 初始化页面闪动问题如何解决?
呈现该问题是因为在 Vue 代码尚未被解析之前,尚无法控制页面中 DOM 的显示,所以会看见模板字符串等代码。
解决方案是,在 css 代码中增加 v-cloak 规定,同时在待编译的标签上增加 v-cloak 属性:
[v-cloak] {display: none;}
<div v-cloak>
{{message}}
</div>
Vue-router 路由有哪些模式?
个别有两种模式:
(1)**hash 模式 **:前面的 hash 值的变动,浏览器既不会向服务器发出请求,浏览器也不会刷新,每次 hash 值的变动会触发 hashchange 事件。(2)**history 模式 **:利用了 HTML5 中新增的 pushState() 和 replaceState() 办法。这两个办法利用于浏览器的历史记录栈,在以后已有的 back、forward、go 的根底之上,它们提供了对历史记录进行批改的性能。只是当它们执行批改时,尽管扭转了以后的 URL,但浏览器不会立刻向后端发送申请。
$nextTick 是什么?
Vue 实现响应式并不是在数据产生后立刻更新 DOM,应用 vm.$nextTick
是在下次 DOM 更新循环完结之后立刻执行提早回调。在批改数据之后应用,则 能够在回调中获取更新后的 DOM。
Vue 中 computed 和 watch 有什么区别?
计算属性 computed:
(1)** 反对缓存 **,只有依赖数据发生变化时,才会从新进行计算函数;(2)计算属性内 ** 不反对异步操作 **;(3)计算属性的函数中 ** 都有一个 get**(默认具备,获取计算属性)** 和 set**(手动增加,设置计算属性)办法;(4)计算属性是主动监听依赖值的变动,从而动静返回内容。
侦听属性 watch:
(1)** 不反对缓存 **,只有数据发生变化,就会执行侦听函数;(2)侦听属性内 ** 反对异步操作 **;(3)侦听属性的值 ** 能够是一个对象,接管 handler 回调,deep,immediate 三个属性 **;(3)监听是一个过程,在监听的值变动时,能够触发一个回调,并 ** 做一些其余事件 **。
action 与 mutation 的区别
mutation
是同步更新,$watch
严格模式下会报错action
是异步操作,能够获取数据后调用mutation
提交最终数据
谈谈对 keep-alive 的理解
keep-alive 能够实现组件的缓存,当组件切换时不会对以后组件进行卸载。罕用的 2 个属性
include/exclude,2 个生命周期
activated,
deactivated
Vue 模板编译原理
Vue 的编译过程就是将 template 转化为 render 函数的过程 分为以下三步
第一步是将 模板字符串 转换成 element ASTs(解析器)第二步是对 AST 进行动态节点标记,次要用来做虚构 DOM 的渲染优化(优化器)第三步是 应用 element ASTs 生成 render 函数代码字符串(代码生成器)
Vue 修饰符有哪些
事件修饰符
- .stop 阻止事件持续流传
- .prevent 阻止标签默认行为
- .capture 应用事件捕捉模式, 即元素本身触发的事件先在此处解决,而后才交由外部元素进行解决
- .self 只当在 event.target 是以后元素本身时触发处理函数
- .once 事件将只会触发一次
- .passive 通知浏览器你不想阻止事件的默认行为
v-model 的修饰符
- .lazy 通过这个修饰符,转变为在 change 事件再同步
- .number 主动将用户的输出值转化为数值类型
- .trim 主动过滤用户输出的首尾空格
键盘事件的修饰符
- .enter
- .tab
- .delete (捕捉“删除”和“退格”键)
- .esc
- .space
- .up
- .down
- .left
- .right
零碎润饰键
- .ctrl
- .alt
- .shift
- .meta
鼠标按钮修饰符
- .left
- .right
- .middle
Vue 性能优化
编码优化:
- 事件代理
keep-alive
- 拆分组件
key
保障唯一性- 路由懒加载、异步组件
- 防抖节流
Vue 加载性能优化
- 第三方模块按需导入(
babel-plugin-component
) - 图片懒加载
用户体验
app-skeleton
骨架屏shellap
p 壳pwa
SEO 优化
- 预渲染