# Vue 基础面试题答案解析
关于答案解析
- Vue2.x ,Vue3.x 相关面试题答案解析过程是根据自身项目实践以及查阅官方文档等最终的得出结论。
- 仅供学习参考,评论区感谢补充和纠错 !
# 1、谈谈你对 SPA 单页面模式的理解,优缺点 ?
答案解析
SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS
- 典型使用 SPA 模式的前端框架有:React、Angular、Vue
- 一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,避免页面的重新加载。
优点:
- 用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
- 基于上面一点,SPA 相对对服务器压力小;
- 前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
缺点:
- 初次加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载;
- 前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;
- SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。
# 2、谈谈你对 MVVM 的理解 ?
答案解析
简短一句话解释:
MVVM 是 Model-View-ViewModel 缩写,也就是把 MVC 中的 Controller 演变成 ViewModel
- Model 层代表数据模型,View 代表 UI 组件,ViewModel 是 View 和 Model 层的桥梁,数据会绑定到 viewModel 层并自动将数据渲染到页面中,视图变化的时候会通知 viewModel 层更新数据。
# 3、MVVM 解决了什么问题 ?
答案解析
当业务程度越来越复杂时,传统的 MVC 暴露出了很多问题,而 MVVM 就是为了解决这些问题出现的。
三个痛点问题:
- 开发者在代码中大量调用相同的 DOM API,处理繁琐 ,操作冗余,使得代码难以维护
- 大量的 DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。
- 当 Model 频繁发生变化,开发者需要主动更新到 View ;当用户的操作导致 Model 发生变化,开发者同样需要将变化的数据同步到 Model 中,这样的工作不仅繁琐,而且很难维护复杂多变的数据状态。
其实,早期 jQuery 的出现就是为了前端能更简洁的操作 DOM 而设计的,但它只解决了第一个问题,另外两个问题始终伴随着前端一直存在 ! MVVM 的出现,完美解决 了 以上三个问题 。
# 4、VueJS 和 ReactJS 有什么相似之处 ?
答案解析
React 和 Vue 有许多相似之处,它们都有:
- 使用 Virtual DOM
- 提供了响应式(Reactive)和组件化 (Composable)的视图组件。
- 将注意力集中保持在核心库,而将其他功能如路由和全局状态管理交给相关的库。
# 5、VueJS 和 ReactJS 有什么不同之处 ?
尽管 VueJS 和 ReactJS 有一些功能相似,但也有一些不同,以表格的形式列出。
功能 | VueJS | ReactJS |
---|---|---|
类型 | JavaScript MVVM 框架,由 MVC 发展而来 | JavaScript 库 |
平台 | 主要关注 Web 开发 | Web 和 原生 |
学习曲线 | 上手更简单,由浅入深,学习成本低 | 陡峭的学习曲线并且需要深入知识 |
简单性 | Vue 比 React 更简单 | React 比 Vue 更复杂 |
引导应用程序 | Vue-cli | CRA (Create React App) |
# 6、VueJS 与 ReactJS 相比有什么优势 ?
答案解析
与 React 相比,Vue 具有以下优势
- Vue 更小且更快
- 方便的模板简化了开发过程
- 相比学习 JSX 它有更简单的 JavaScript 语法
- 深受国内企业和开发者喜爱
# 7、ReactJS 与 VueJS 相比有什么优势 ?
答案解析
与 Vue 相比,React 具有以下优势
- ReactJS 在大型应用程序开发中提供了更大的灵活性
- 易于测试
- 非常适合创建移动应用程序
- 生态系统规模大,成熟度高
# 8、VueJS 和 AngularJS 有什么不同之处 ?
答案解析
Vue 和 Angular 的语法在某些地方很常见,因为 Angular 是 Vuejs 开发的基础。 但是 Vuejs 和 Angular 之间也有很多不同之处
功能 | VueJS | AngularJS |
---|---|---|
复杂度 | 易于学习,简单的 API 和设计 | 这个框架有点庞大,需要一些 typescript 等方面的学习曲线。 |
数据绑定 | Vue 在不同组件间强制使用单向数据流。这使应用中的数据流更加清晰易懂 | 双向绑定 |
学习曲线 | 上手更简单,由浅入深,学习成本低 | 陡峭的学习曲线并且需要深入知识 |
创办者 | 由中国人尤雨溪创建 | 由谷歌提供支持 |
初版本 | 2014 年 2 月 | 2016 年 9 月 |
模型 | 基于虚拟 DOM(文档对象模型) | 基于 MVC(模型-视图-控制器) |
编写 | JavaScript,最新 Vue3.x 支持 TypeScript | TypeScript |
# 9、VueJS 的主要功能有哪些 ?
答案解析
下面是一些 VueJS 提供的主要功能
- 虚拟 DOM:它使用的虚拟 DOM 类似于其他现有的框架,例如 ReactJS,Ember 等。虚拟内存是一个轻量级的内存中内存 HTML DOM 的表示形式并且不影响 DOM 的更新
- 组件:在 VueJS 应用程序中创建可复用的自定义元素
- 模板: VueJS 提供基于 HTML 的模板和 DOM 和 Vue 实例的数据绑定
- 路由:通过 vue-router 实现页面之间的导航
- 轻量级: VueJS 轻量于其他框架是一个量级的库
# 10、描述 Vue 组件生命周期(父子组件)
答案解析
单组件生命周期
beforeCreate,created,beforeMount,beforeMounted,beforeUpdate,updated,beforeDestroy,destroyed
父子组件生命周期关系
- 创建: 父 created --> 子 created --> 子 mounted --> 父 mounted
- 更新: 父 beforeUpdate --> 子 beforeUpdate --> 子 updated --> 父 updated
- 销毁: 父 beforeDestryy --> 子 beforeDestryy --> 子 destroyed --> 父 destroyed
# 11、Vue 响应式数据原理(Vue2.x & Vue3.0)有什么区别 ?
答案解析
Vue2.x
- 在初始化数据时,会使用
Object.defineProperty
重新定义data
中的所有属性。 - 当页面使用对应属性时,首先会进行依赖收集(收集当前组件的 watcher),如果属性发生变化会通知相关依赖进行派发更细(发布订阅模式)
vue3.0
- 采用 ES6 中的
proxy
代替Object.defineProperty
做数据监听。
# 12、Proxy 与 Object.defineProperty 的优劣对比 ?
答案解析
Proxy 的优势如下:
- Proxy 可以直接监听对象而非属性
- Proxy 可以直接监听数组的变化
- Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的
- Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改
- Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利
Object.defineProperty 的优势如下:
- 兼容性好,支持到 IE9
# 13、v-if 和 v-show 的区别 ?
答案解析
- v-if 在编译过程中会被转化成三元表达式,条件不满足时不渲染此节点。表达式通过的情况下将元素渲染到 DOM 中。
- v-show 会被编译成指令,条件不满足时控制样式将对应节点隐藏 (display:none)。条件满足时基于 CSS display 属性来显示元素
- v-if 支持 v-else 和 v-else-if 指令,而 v-show 不支持 else 指令。
- v-if 有更高的切换开销,而 v-show 有更高的初始化渲染开销
- v-if 支持
<template>
选项卡,但 v-show 不支持
使用场景
- v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景
- v-show 适用于需要非常频繁切换条件的场景
# 14、v-if 与 v-for 为什么不建议一起使用 ?
答案解析
- v-for 和 v-if 不要在同一个标签中使用,因为解析时先解析 v-for 再解析 v-if(v-for 指令比 v-if 优先级高)。
如果遇到需要同时使用时可以考虑写成计算属性的方式。(有两种情况下会尝试这种组合)如下:
# (1)过滤列表的项
<!-- 例如,如果你尝试使用 v-if 标记过滤列表 -->
<ul>
<li
v-for="user in users"
v-if="user.isActive"
:key="user.id"
>
{{ user.name }}
<li>
</ul>
<!-- 这可以使用在初始列表上使用计算属性预过滤来避免。 -->
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>
# (2)避免渲染应该被隐藏的列表
<!-- 例如,你想根据条件检查用户是否显示还是隐藏 -->
<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>
# 15、为什么使用 for 指令时需要 key 属性 ?
答案解析
为了跟踪每个节点的特征,从而重用和重排存在的元素,你需要为每一个 v-for
迭代的项提供一个 key
属性。一个理想的 key 值是条目的唯一 id
<!--举个例子-->
<div v-for="item in items" :key="item.id">
{{item.name}}
</div>
因此,只要有可能,总是建议给 v-for 提供一个 key 值,除非迭代的 DOM 内容很简单。
注:不应该使用非基本类型的值,如对象和数组作为 v-for 的 key,使用 String 或 Number 类型替代。
# 16、如何复用有 key 属性的元素 ?
Vue 总是尝试尽可能高效地渲染元素,因此它会试图用重用元素替代从零开始构建。但这种行为会在有些情况下导致一些问题
<!-- 例如,如果你尝试在 v-if 和 v-else 块中渲染同样的 input 元素,它将会像下面这样在切换后保留先前的值 -->
<template v-if="loginType === 'Admin'">
<label>Admin</label>
<input placeholder="Enter your ID" />
</template>
<template v-else>
<label>Guest</label>
<input placeholder="Enter your name" />
</template>
这种情况下,它不应该重用。我们可以像下面这样在 input 元素上使用 key 属性分离
<template v-if="loginType === 'Admin'">
<label>Admin</label>
<input placeholder="Enter your ID" key="admin-id" />
</template>
<template v-else>
<label>Guest</label>
<input placeholder="Enter your name" key="user-name" />
</template>
上面的代码确保了两个输入框失独立的,且不会影响彼此。
# 17、v-model 双向数据绑定原理
答案解析
vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式 的方式来实现的,也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变; 核心:Object.defineProperty()
方法。
v-model
本质上是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件
- text 和 textarea 元素使用 value 属性和 input 事件
- checkbox 和 radio 使用 checked 属性和 change 事件
- select 字段将 value 作为 prop 并将 change 作为事件
# 18、$route 和 $router 有什么区别 ?
答案解析
- $route 是路由信息对象,包括 path,params,hash,query,fullPath,matched,name 等路由信息参数。
- 而$router 是路由实例对象,包括了路由的跳转方法,钩子函数等。
# 19、Vuex 页面刷新数据丢失怎么解决 ?
答案解析
- 需要做 vuex 数据持久化 一般使用本地存储的方案来保存数据 可以自己设计存储方案 也可以使用第三方插件
- 推荐使用 vuex-persist 插件,它就是为 Vuex 持久化存储而生的一个插件。不需要你手动存取 storage ,而是直接将状态保存至 cookie 或者 localStorage 中
# 20、你都做过哪些 Vue 的性能优化,还有有哪些可以做 ?
答案解析
(1)编码阶段
- 不要在模板里面写过多表达式
- 尽量减少 data 中的数据,data 中的数据都会增加
getter
和setter
,会收集对应的watcher
- 不需要响应式的数据不要放到 data 中(可以用 Object.freeze() 冻结数据)
- 对象层级不要过深,否则性能就会差
- computed 和 watch 区分使用场景
- v-if 和 v-for 不能连用
- 如果需要使用 v-for 给每项元素绑定事件时使用事件代理
- SPA 页面采用
keep-alive
缓存组件 - 频繁切换的使用 v-show,不频繁切换的使用 v-if
- v-for 遍历必须加 key,key 最好是 id 值,且避免同时使用 v-if
- 使用路由懒加载、异步组件
- 防抖、节流运用
- 第三方模块按需导入
- 大数据列表和表格性能优化 - 虚拟列表/虚拟表格
- 图片懒加载
(2)搜索引擎 SEO 优化
- 预渲染
- 服务端渲染 SSR,nuxt.js
(3)打包优化
- 压缩代码
- Tree Shaking / Scope Hoisting
- 使用 CDN 加载第三方模块
- 多线程打包 happypack
- splitChunks 抽离公共文件
- sourceMap 优化
(4)用户体验
- 骨架屏
- PWA 渐进式 Web 应用,使用多种技术来增强 web app 的功能,让网页应用呈现和原生应用相似的体验。
# 21、Vue 有了数据响应式,为何还要 diff ?
答案解析
核心原因:粒度
React
通过setState
知道有变化了,但不知道哪里变化了,所以需要通过 diff 找出变化的地方并更新 dom。- Vue 已经可以通过响应式系统知道哪里发生了变化,但是所有变化都通过响应式会创建大量 Watcher,极其消耗性能,因此 vue 采用的方式是通过响应式系统知道哪个组件发生了变化,然后在组件内部使用 diff。
- 这样的中粒度策略,即不会产生大量的 Watcher,也使 diff 的节点减少了,一举两得。
# 22、Vue 组件中 data 为什么必须是一个函数 ?
答案解析
复用组件的时候,都会返回一份新的 data,相当于每个组件实例都有自己私有的数据空间,不会共享同一个 data 对象。
# 23、Vue3.x 用过吗,了解多少 ?
答案解析
- 响应式原理的改变 Vue3.x 使用 Proxy 取代 Vue2.x 版本的
Object.defineProperty
- 组件选项声明方式 Vue3.x 使用 Composition API setup 是 Vue3.x 新增的一个选项, 他是组件内使用 Composition API 的入口。
- 模板语法变化 slot 具名插槽语法 自定义指令 v-model 升级
- 其它方面的更改 Suspense 支持 Fragment(多个根节点)和 Protal(在 dom 其他部分渲染组建内容)组件,针对一些特殊的场景做了处理。 基于 treeshaking 优化,提供了更多的内置功能
- 等等 ......
# 24、Vue 中条件指令有哪些 ?
答案解析
VueJS 提供了通过指令基于条件来显示或隐藏元素。可用的指令有:v-if, v-else, v-else-if and v-show
(1) v-if: v-if 指令基于给定的表达式添加或移除 DOM 元素
<!-- 下面的 button 在 isLoggedIn 被设置为 false 时不会显示 -->
<button v-if="isLoggedIn">Logout</button>
<!--
将全部元素都包在一个 <template> 元素里这样也可以使用一个 v-if 指令基于条件控制多个元素。
例如,你可以将条件同事应用于 label 和 button。
-->
<template v-if="isLoggedIn">
<label> Logout </button>
<button> Logout </button>
</template>
(2)v-else: 这个指令只会在相邻的 v-if 条件为 false 时用来显示内容,这类似于任何编程语言中的 else 块用来显示可选的内容,并且在它前面是 v-if 或 v-else-if 块,你不需要传递任何值给它
<!-- 例如,v-else 在 isLoggedIn 被设置为 false (未登录)时显示 LogIn 按钮 -->
<button v-if="isLoggedIn"> Logout </button>
<button v-else> LogIn </button>
(3)v-else-if: 当我们需要两个以上选项检查时,就会用到这个指令
<!-- 例如,当 ifLoginDisabled 属性被设置为 true 时我们想要显示一些文案替代 LogIn 按钮。这就可以通过 v-else 指令实现 -->
<button v-if="isLoggedIn"> Logout </button>
<label v-else-if="isLoginDisabled"> User login disabled </label>
<button v-else> Log In </button>
(4)v-show: 这个指令类似于 v-if,但是它会将所有元素渲染到 DOM 中并通过 CSS 的 display 属性来 显示 /隐藏 元素。这个指令被推荐用于需要频繁切换开关的元素
<span v-show="user.name">Welcome user,{{user.name}}</span>
#
大厂最新技术学习分享群
微信扫一扫进群,获取资料
X