2023年最新的Vue全套面试题(含答案)
为什么需要懒加载? 像vue这种单页面应用,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,时间过长,会出啊先长时间的白屏,即使做了loading也是不利于用户体验,而运用懒加载则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时vue异步组件es提案的import()webpack...
个人录制的Vue全套项目学习视频:请观看B站
Vue2-第二版-后台管理系统项目实战/vue+element-ui/vue经典全套系统案例讲解_哔哩哔哩_bilibili
2023前端高频面试题-JS高频面试题(上)_哔哩哔哩_bilibili
1、介绍一下MVC MVVM
1. 什么是MVVM?

2. 什么是MVC?
MVC是应用最广泛的软件架构之一,一般MVC分为:Model(模型),View(视图),Controller(控制器)。 这主要是基于分层的目的,让彼此的职责分开.View一般用过Controller来和Model进行联系。Controller是Model和View的协调者,View和Model不直接联系。基本都是单向联系。M和V指的意思和MVVM中的M和V意思一样。C即Controller指的是页面业务逻辑。MVC是单向通信。也就是View跟Model,必须通过Controller来承上启下。
Model(模型)表示应用程序核心(如数据库)。
View(视图)显示效果(HTML页面)。
Controller(控制器)处理输入(业务逻辑)。
MVC 模式同时提供了对 HTML、CSS 和 JavaScript 的完全控制。
Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。 通常模型对象负责在数据库中存取数据。
View(视图)是应用程序中处理数据显示的部分。 通常视图是依据模型数据创建的。
Controller(控制器)是应用程序中处理用户交互的部分。 通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
优点:
- 低耦合
- 重用性高
- 生命周期成本低
- 部署快
- 可维护性高
- 有利软件工程化管理
3. MVC与MVVM的区别:
MVC和MVVM的区别并不是VM完全取代了C,ViewModel存在目的在于抽离Controller中展示的业务逻辑,而不是替代Controller,其它视图操作业务等还是应该放在Controller中实现。也就是说MVVM实现的是业务逻辑组件的重用。
- MVC中Controller演变成MVVM中的ViewModel
- MVVM通过数据来显示视图层而不是节点操作
- MVVM主要解决了MVC中大量的dom操作使页面渲染性能降低,加载速度变慢,影响用户体验
2、为什么data是一个函数
组件的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一分新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。
3、Vue组件通讯有哪些方式?
1、props 和 $emit。父组件向子组件传递数据是通过props传递的,子组件传递给父组件是通过$emit触发事件来做到的。
2、$parent 和 $children 获取单签组件的父组件和当前组件的子组件。
3、$attrs 和 $listeners A -> B -> C。Vue2.4开始提供了$attrs和$listeners来解决这个问题。
4、父组件中通过 provide 来提供变量,然后在子组件中通过 inject 来注入变量。(官方不推荐在实际业务中适用,但是写组件库时很常用。)
5、$refs 获取组件实例。
6、envetBus 兄弟组件数据传递,这种情况下可以使用事件总线的方式。
7、vuex 状态管理
4、Vue的生命周期方法有哪些?一般在哪一步发送请求?
beforeCreate 在实例初始化之后,数据观测(data observe)和 event/watcher 事件配置之前被调用。在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问。
created 实例已经创建完成之后被调用。在这一步,实例已经完成以下的配置:数据观测(data observe ),属性和方法的运算,watch/event 事件回调。这里没有 $el,如果非要想与 DOM 进行交互,可以通过vm.$nextTick 来访问 DOM。
beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted 在挂载完成后发生,在当前阶段,真实的 Dom 挂载完毕,数据完成双向绑定,可以访问到 Dom节点。
beforeUpdate 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁 (patch)之前。可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。(数据修改页面未修改)
updated 发生在更新完成之后,当前阶段组件 Dom 已经完成更新。要注意的是避免在此期间更新数据,因为这个可能导致无限循环的更新,该钩子在服务器渲染期间不被调用。
beforeDestroy 实例销毁之前调用。在这一步,实例仍然完全可用。我们可以在这时进行 善后收尾工作,比如清除定时器。
destroyed Vue实例销毁后调用。调用后,Vue实例指示的东西都会解绑定,所有的事件监听器会被移除,左右的子实例也会被销毁,该钩子在服务器端渲染不被调用。
activated keep-alive 专属,组件被激活时调用
deactivated keep-alive 专属,组件被销毁时调用
异步请求在哪一步发起?
可以在钩子函数 created、beforeMount、mounted 中进行异步请求,因为在这三个钩子函数中,data已经创建,可以将服务器端返回的数据进行赋值。
如果异步请求不需要依赖 DOM 推荐加载 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:
- 能更快获取到服务端数据,减少页面loading时间;
如果依赖DOM元素:需要再mounted里面进行请求
5、v-if 和 v-show 的区别
v-if 在编译过程中会被转化成三元表达式,条件不满足时不渲染此节点。元素销毁和重建控制显示隐藏
v-show 会被编译成指令,条件不满足时控制样式将此节点隐藏(display:none) css样式控制
使用场景
v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景。
v-show 适用于需要非常频繁切换条件的场景。
扩展补充:display:none 、 visibility:hidden 和 opacity:0 之间的区别?
三者公共点都是 隐藏。
不同点:
- 是否占据空间。
display:none,隐藏之后不占位置;visibility:hidden、opacity:0,隐藏后任然占据位置。
- 子元素是否继承。
display:none --- 不会被子元素继承,父元素都不存在了,子元素也不会显示出来。
visibility:hidden --- 会被子元素继承,通过设置子元素 visibility:visible 来显示子元素。
opacity:0 --- 会被子元素继承,但是不能设置子元素 opacity:0 来先重新显示。
- 事件绑定。
display:none 的元素都已经不存在了,因此无法触发他绑定的事件。
visibility:hidden 不会触发他上面绑定的事件。
opacity:0 元素上面绑定的事件时可以触发的。
- 过度动画。
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 通知父组件去修改。
多种方法实现:在子组件直接用 v-model 绑定父组件传过来的 props
方法1:利用get set方法
方法2:监听器
方法3:对象写法(推荐)
8、computed 和 watch 的区别和运用的场景
computed 是计算属性,依赖其它属性计算值,并且 computed 的值有缓存,只有当计算值变化才会返回内容,他可以设置getter和setter。
watch 监听到值的变化就会执行回调,在回调中可以进行一系列的操作。
计算属性一般用在模板渲染中,某个值是依赖其它响应对象甚至是计算属性而来;
而侦听属性适用于观测某个值的变化去完成一段复杂的业务逻辑。
9、v-if 和 v-for 为什么不建议一起使用
v-for和v-if不要在同一标签中使用,因为解析时先解析v-for在解析v-if。如果遇到需要同时使用时可以考虑写成计算属性的方式。
永远不要把 v-if 和 v-for 同时用在同一个元素上,带来性能方面的浪费(每次渲染都会先循环再进行条件判断)
如果避免出现这种情况,则在外层嵌套template(页面渲染不生成dom节点),在这一层进行v-if判断,然后在内部进行v-for循环
<template v-if="isShow">
<p v-for="item in items">
</template>
如果条件出现在循环内部,可通过计算属性computed提前过滤掉那些不需要显示的项
computed: {
items: function() {
return this.list.filter(function (item) {
return item.isShow
})
}
}
10. Vue 2.0 响应式数据的原理(常问)
11、Vue 如何检测数组变化
//使用该方法进行更新视图
// vm.$set,Vue.set的一个别名
vm.$set(vm.items, indexOfItem, newValue)
12、Vue的父子组件生命周期钩子函数执行顺序
13、v-model 双向绑定的原理是什么?
14. Vue3.x 响应式数据可以从以下方面展开回答:
15. vue2.x 和 vuex3.x 渲染器的 diff 算法分别说一下?
- 同级比较,再比较子节点
- 先判断一方有子节点一方没有子节点的情况(如果新的 children 没有子节点,将旧的子
- 节点移除)
- 比较都有子节点的情况(核心 diff)
- 递归比较子节点
16. hash 模式和 history 模式的实现原理
- 首先是在 URL 的展示上,hash 模式有“#”,history 模式没有
- 刷新页面时,hash 模式可以正常加载到 hash 值对应的页面,而 history 没有处理的话,会返回404,一般需要后端将所有页面都配置重定向到首页路由
- 在兼容性上,hash 可以支持低版本浏览器和 IE
17、vue-router 路由钩子函数是什么?执行顺序是什么?
18、vue-router 动态路由是什么?有什么问题。
1 const User = {
2 template: "
3 User", };
4 const router = new VueRouter({
5 routes: [
6 // 动态路径参数 以冒号开头
7 { path: "/user/:id", component: User },
8 ],
9 });
1 watch:{
2 "router":function(){
3 this.getData(this.$router.params.xxx)
4 }
5 }
19、谈一下对 vuex 的个人理解
- State:定义了应用状态的数据结构,可以在这里设置默认的初始化状态。
- Getter:允许组件从Store中获取数据,mapGetters 辅助函数仅仅是将 store 中的
- getter 映射到局部计算属性。
- Mutation:是唯一更改 store 中状态的方法,且必须是同步函数。
- Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步请求。
- Module:允许将单一的 Store 拆分更多个 store 且同时保存在单一的状态树中。
20、Vuex 页面刷新数据丢失怎么解决?
21、vue 中使用了哪些设计模式?
- 工厂模式 - 传入参数即可创建实例 虚拟 DOM 根据参数的不同返回基础标签的 Vnode 和组件 Vnode。
- 单例模式 - 整个程序有且仅有一个实例 vuex 和 vue-router 的插件注册方法 install 判断如果系统存在实例就直接返回掉。
- 发布-订阅模式。(vue 事件机制)
- 观察者模式。(响应式数据原理)
- 装饰器模式(@装饰器的用法)
- 策略模式,策略模式指对象有某个行为,但是在不同的场景中,该行为有不同的实现方案 - 比如选项的合并策略。
22、你都做过哪些 Vue 的性能优化?
- 对象层级不要过深,否则性能就会差。
- 不需要响应式的数据不要放在 data 中(可以使用 Object.freeze() 冻结数据)
- v-if 和 v-show 区分使用场景
- computed 和 watch 区分场景使用
- v-for 遍历必须加 key,key最好是id值,且避免同时使用 v-if
- 大数据列表和表格性能优化 - 虚拟列表 / 虚拟表格
- 防止内部泄露,组件销毁后把全局变量和时间销毁
- 图片懒加载
- 路由懒加载
- 异步路由
- 第三方插件的按需加载
- 适当采用 keep-alive 缓存组件
- 防抖、节流的运用
- 服务端渲染 SSR or 预渲染
23、nextTick 的作用是什么?他的实现原理是什么
- Promise:可以将函数延迟到当前函数调用栈最末端
- MutationObserver :是 H5 新加的一个功能,其功能是监听 DOM 节点的变动,在所有 DOM 变动完成后,执行回调函数setImmediate:用于中断长时间运行的操作,并在浏览器完成其他操作(如事件和显 示更新)后立即运行回调函数
- 如果以上都不行则采用 setTimeout 把函数延迟到 DOM 更新之后再使用,原因是宏任务消耗大于微任务,优先使用微任务,最后使用消耗最大的宏任务
24、keep-alive 使用场景和原理
1 // keep-alive 内部的声明周期函数
2 created () {
3 this.cache = Object.create(null)
4
5 this.keys = []
6 }
25、Vue.set 方法原理
- 在实例创建之后添加新的属性到实例上(给响应式对象新增属性)
- 直接更改数组下标来修改数组的值。
26. Proxy 相比 defineProperty 的优势在哪里
- Object.defineProperty 只能劫持对象属性的 getter 和 setter 方法。
- Object.definedProperty 不支持数组(可以监听数组,不过数组方法无法监听自己重写),更准确的说是不支持数组的各种 API(所以 Vue 重写了数组方法。
- Proxy 是直接代理劫持整个对象。
- Proxy 可以直接监听对象和数组的变化,并且有多达 13 种拦截方法。
更多推荐