持续更新中...
面试传送门:
有些问题的答案描述的比较浅,如果答案里有链接的话,强烈建议点进去看一下,会知道更多细节的问题,可以了解的更多!
001.说一下vue中的MVVM?
即Model-View-ViewModel。
Vue是以数据为驱动的,Vue自身将DOM和数据进行绑定,一旦创建绑定,DOM和数据将保持同步,每当数据发生变化,DOM会跟着变化
ViewModel是Vue的核心,它是Vue的一个实例。Vue实例时作用域某个HTML元素上的,这个HTML元素可以是body,也可以是某个id所指代的元素。
DOM Listeners和Data Bindings是实现双向绑定的关键。DOM Listeners监听页面所有View层DOM元素的变化,当发生变化,Model层的数据随之变化;Data Bindings监听Model层的数据,当数据发生变化,View层的DOM元素随之变化。
002.v-show与v-if的区别
条件渲染指令,与v-if不同的是,无论v-show的值为true或false,元素都会存在于HTML代码中;而只有当v-if的值为true,元素才会存在于HTML代码中。v-show指令只是设置了元素CSS的style值
003.指令keep-alive
在vue-router写着keep-alive,keep-alive的含义:如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。为此可以添加一个keep-alive指令
004.路由嵌套
路由嵌套会将其他组件渲染到该组件内,而不是进行整个页面跳转。
router-view本身就是将组件渲染到该位置,
005.说一下v-model的原理?
简单的说,就是 :value 和 @input 的结合使用,v-model就是他们两个的语法糖。
006.vue中使用事件名
在vuejs中,我们经常要绑定一些事件,有时候给DOM元素绑定,有时候给组件绑定。
绑定事件在HTML中用v-on:click="event",可以简写为:@click="event"
007.vue.js是什么
Vue.js是一套构建用户界面的 渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。
Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合。
另一方面,Vue 完全有能力驱动采用单文件组件和Vue生态系统支持的库开发的复杂单页应用。
Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件
008.route 和 router 的区别是什么?
route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
router是“路由实例对象”,包括了路由的跳转方法(push、replace),钩子函数等。
009.mvvm和mvc区别?它和其它框架(jquery)的区别是什么?哪些场景适合?
mvc和mvvm其实区别并不大。都是一种设计思想。主要就是mvc中Controller演变成mvvm中的viewModel。mvvm主要解决了mvc中大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。
区别:vue数据驱动,通过数据来显示视图层而不是节点操作。
场景:数据操作比较多的场景,更加便捷
010.vue的优点是什么?
低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。
011.vuex面试相关
(1)vuex是什么?
vue框架中状态管理。
(2)vuex有哪几种属性?
有五种,分别是 State、 Getters、Mutations 、Actions、 Module
vuex的State特性
A、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于一般Vue对象里面的data
B、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
C、它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中
vuex的Getters特性
A、getters 可以对State进行计算操作,它就是Store的计算属性
B、 虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用
C、 如果一个状态只在一个组件内使用,是可以不用getters
vuex的Mutations特性
Actions 类似于 mutations,不同在于:Actions 提交的是 mutations,而不是直接变更状态;Actions 可以包含任意异步操作。
(3)不用Vuex会带来什么问题?
可维护性会下降,想修改数据要维护三个地方;
可读性会下降,因为一个组件里的数据,根本就看不出来是从哪来的;
增加耦合,大量的上传派发,会让耦合性大大增加,本来Vue用Component就是为了减少耦合,现在这么用,和组件化的初衷相背。
012.如何让CSS只在当前组件中起作用
将当前组件的<style>修改为<style scoped>
013.响应式系统简述:
- 任何一个 Vue Component 都有一个与之对应的 Watcher 实例
- Vue 的 data 上的属性会被添加 getter 和 setter 属性
- 当 Vue Component render 函数被执行的时候, data 上会被 触碰(touch), 即被读, getter 方法会被调用, 此时 Vue 会去记录此 Vue component 所依赖的所有 data。(这一过程被称为依赖收集)
- data 被改动时(主要是用户操作), 即被写, setter 方法会被调用, 此时 Vue 会去通知所有依赖于此 data 的组件去调用他们的 render 函数进行更新
014.谈谈你对虚拟DOM的理解?
首先,我们都知道在前端性能优化的一个秘诀就是尽可能少地操作DOM,不仅仅是DOM相对较慢,更因为频繁变动DOM会造成浏览器的回流或者重回,这些都是性能的杀手,因此我们需要这一层抽象,在patch过程中尽可能地一次性将差异更新到DOM中,这样保证了DOM不会出现性能很差的情况.
其次,现代前端框架的一个基本要求就是无须手动操作DOM,一方面是因为手动操作DOM无法保证程序性能,多人协作的项目中如果review不严格,可能会有开发者写出性能较低的代码,另一方面更重要的是省略手动DOM操作可以大大提高开发效率.
015.vue 中 key 值的作用?
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key 的作用主要是为了高效的更新虚拟DOM。
016.vue 中怎么重置 data?
使用Object.assign(),vm.$data可以获取当前状态下的data,
vm.$options.data可以获取到组件初始化状态下的data。
Object.assign(this.$data, this.$options.data())
017.组件中写 name 有什么作用?
- 项目使用 keep-alive 时,可搭配组件 name 进行缓存过滤
- DOM 做递归组件时需要调用自身 name
- vue-devtools 调试工具里显示的组见名称是由vue中组件name决定的
018.为什么需要 nextTick,nextTick 是做什么的?
Vue 是异步修改 DOM 的并且不鼓励开发者直接接触 DOM,但有时候业务需要必须对数据更改--刷新后的 DOM 做相应的处理,这时候就可以使用 Vue.nextTick(callback)这个 api 了。
$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM
019.vue 首屏加载优化方案
- 把不常改变的库放到 index.html 中,通过 cdn 引入
- vue 路由的懒加载
- 不生成 map 文件(找到 config/index.js,修改为 productionSourceMap: false)
- vue 组件尽量不要全局引入
- 使用更轻量级的工具库
- 开启gzip压缩
- 首页单独做服务端渲染
020.vue3.0 有没有过了解?
关于vue 3.0,大致说了三个点,
第一个是关于提出的新API setup()函数,
第二个说了对于Typescript的支持,
最后说了关于替换 Object.defineProperty 为 Proxy 的支持。
详细说了下关于Proxy代替带来的性能上的提升,因为传统的原型链拦截的方法,无法检测对象及数组的一些更新操作,但使用Proxy又带来了浏览器兼容问题。
021.说一下vue的双向绑定数据的原理
vue 实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。
022.vue如何实现按需加载配合webpack设置?
webpack中提供了require.ensure()来实现按需加载。以前引入路由是通过import 这样的方式引入,改为const定义的方式进行引入。
不进行页面按需加载引入方式:import home from ‘…/…/common/home.vue’
进行页面按需加载的引入方式:const home = r => require.ensure( [], () => r (require(’…/…/common/home.vue’)))
023.vue 组件 data 为什么必须是函数?
因为js本身的特性带来的,如果 data 是一个对象,那么由于对象本身属于引用类型,当我们修改其中的一个属性时,会影响到所有Vue实例的数据。如果将 data 作为一个函数返回一个对象,那么每一个实例的 data 属性都是独立的,不会相互影响了
024.计算属性 computed 和事件 methods 有什么区别
我们可以将同一函数定义为一个 method 或者一个计算属性。对于最终的结果,两种方式是相同的
不同点:
- computed: 计算属性是基于它们的依赖进行缓存的,只有在它的相关依赖发生改变时才会重新求值
- 对于 method ,只要发生重新渲染,method 调用总会执行该函数
Vue中watch、computed与methods的联系和区别
025.vue 等单页面应用的优缺点:
优点:
- 良好的交互体验
- 良好的前后端工作分离模式
- 减轻服务器压力
缺点:
- SEO难度较高
- 前进、后退管理
- 初次加载耗时多
026.vue生命周期
vue的生命周期主要分为:创建前后、载入前后、更新前后、销毁前后
beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed
027.Vue 导航守卫(路由的生命周期)
全局的
- router.beforeEach
- router.beforeResolve
- router.afterEach
单个路由独享的
- beforeEnter
组件级的
- beforeRouteEnter
- beforeRouteUpdate
- beforeRouteLeave
028.常见的跨域解决方案
前端配置vue.config.js
后端配置各种头
jsonp(只能解决get)
步骤:
1).去创建一个script标签
2).script的src属性设置接口地址 3).接口参数,必须要带一个自定义函数名,要不然后台无法返回数据 4).通过定义函数名去接受返回的数据
029.什么是webpack及其优点
- 打包:可以把多个JavaScript文件打包成一个文件,减少服务器压力和下载宽带
- 转换:把扩展语言转换成为普通的JavaScript,让浏览器顺利运行。
- 优化:肩负起了优化和提升性能的责任
030.vue中项目如何优化?
- data优化
- SPA首屏加载优化
- 组件优化
- 巧妙利用指令v-if(show),使用v-for要绑定key
- 使用Object.freeze
- 路由懒加载
- 动态导入组件
- 图片懒加载
- 第三方模块按需导入
- 骨架屏
- PWA缓存
- 预渲染
- 服务端渲染SSR
- 缓存和压缩
- HTTP优化
031.vue递归组件的使用
032.vue的mode中hash与history的区别
hash模式重新加载的时候只加载#后面的
history模式则是整个地址重新加载,不过他可以保存历史记录,方便前进后退
vue-router 有 3 种路由模式:hash、history、abstract
- hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器;
- history : 依赖 HTML5 History API 和服务器配置。具体可以查看 HTML5 History 模式;
- abstract : 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式.
033.vue中常用的命令
v-if v-show区别
v-for
v-model
v-bind
v-on
034.vue 的父组件和子组件生命周期钩子函数执行顺序?
vue 的父组件和子组件生命周期钩子函数执行顺序?
- 加载渲染过程
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted - 子组件更新过程
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated - 父组件更新过程
父 beforeUpdate -> 父 updated - 销毁过程
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
035.在哪个生命周期内调用异步请求?
可以在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。但是本人推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:
- 能更快获取到服务端数据,减少页面 loading 时间;
- ssr 不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性;
036.组件中 data 为什么是一个函数?
因为组件是用来复用的,且 JS 里对象是引用关系,如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值会相互影响。
如果组件中 data 选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的 data 属性值不会互相影响;而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。
037.vue组件间通信有哪几种方式?
- props
- $emit
- $attr
- $listener
- provide inject (隔代通信)
- $parent $children
- vuex
038.Proxy 与 Object.defineProperty 优劣对比
Proxy 的优势如下:
- Proxy 可以直接监听对象而非属性;
- Proxy 可以直接监听数组的变化;
- Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的;
- Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改;
- Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利;
Object.defineProperty 的优势如下:
- 兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平,因此 Vue 的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重写。
039.虚拟 DOM 的优缺点?
优点:
- 保证性能下限: 框架的虚拟 DOM 需要适配任何上层 API 可能产生的操作,它的一些 DOM 操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虚拟 DOM 至少可以保证在你不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限;
- 无需手动操作 DOM: 我们不再需要手动去操作 DOM,只需要写好 View-Model 的代码逻辑,框架会根据虚拟 DOM 和 数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率;
- 跨平台: 虚拟 DOM 本质上是 JavaScript 对象,而 DOM 与平台强相关,相比之下虚拟 DOM 可以进行更方便地跨平台操作,例如服务器渲染、weex 开发等等。
缺点:
- 无法进行极致优化: 虽然虚拟 DOM + 合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化。
040.虚拟 DOM 实现原理?
虚拟 DOM 的实现原理主要包括以下 3 部分:
- 用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;
- diff 算法 — 比较两棵虚拟 DOM 树的差异;
- pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。
041.vue插槽的使用?
默认插槽
具名插槽
作用域插槽
042.active-class是哪个组件的属性?
vue-router模块的router-link组件。
043.怎么定义vue-router的动态路由以及如何获取传过来的动态参数?
在router目录下的index.js文件中,对path属性加上/:id。使用route对象的params.id。
044.vue-loader是什么?使用它的用途有哪些?
vue文件的一个加载器。
用途:js可以写es6、style样式可以scss或less、template可以加jade等根据官网的定义,
vue-loader 是 webpack 的一个 loader,用于处理 .vue 文件.
045.为什么避免 v-if 和 v-for 用在一起?
当Vue 处理指令时,v-for 比 v-if 具有更高的优先级,这意味着v-if将分别重复运行于每个v-for循环中。通过v-if 移动到容器元素,不会再重复遍历列表中的每个值。取而代之的是,我们只检查它一次,且不会在 v-if 为否的时候运算 v-for。
046.vue中Class 与 Style 如何动态绑定?
047.怎样理解 Vue 的单向数据流?
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改。
048.直接给一个数组项赋值,Vue 能检测到变化吗?
由于 JavaScript 的限制,Vue 不能检测到以下数组的变动:
- 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:vm.items.length = newLength
049.vue.js的核心是什么?
- 数据驱动(响应式):data中的数据变了,视图才会变
- 组件化:拆组装,目的在于重用,方便,脏活累活一次干完,之后就轻松了
050.vue的常用修饰符?
- 事件修饰符:
.stop stopPropagation 阻止冒泡
.prevent preventDefault 阻止默认行为
.self 事件作用在自己身上才触发
.once 事件只触发一次 - 键盘修饰符
.enter 回车键
.esc 退出键 - v-model 指令修饰符
.lazy 由监听oninput事件转为onchange事件
.number 尽量将文本框中的值转为数字,能转就转,不能转就不转
.trim 去掉字符串的首尾空格
051.vue和react有什么区别?
- react整体是函数式的思想,把组件设计成纯组件,状态和逻辑通过参数传入,所以在react中,是单向数据流;
- vue的思想是响应式的,也就是基于是数据可变的,通过对每一个属性建立Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟dom。
052.请说出vue.cli项目中src目录每个文件夹和文件的用法?
assets文件夹是放静态资源;
components是放组件;
router是定义路由相关的配置;
view视图;
app.vue是一个应用主组件;
main.js是入口文件;
053.单页面应用和多页面应用区别及优缺点?
单页面应用(SPA),通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载所有必须的 html, js, css。所有的页面内容都包含在这个所谓的主页面中。但在写的时候,还是会分开写(页面片段),然后在交互的时候由路由程序动态载入,单页面的页面跳转,仅刷新局部资源。多应用于pc端。
多页面(MPA),就是指一个应用中有多个页面,页面跳转时是整页刷新
单页面的优点:
用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小
前后端分离
页面效果会比较炫酷(比如切换页面内容时的专场动画)
单页面缺点:
初次加载时耗时多
页面复杂度提高很多
导航不可用,如果一定要导航需要自行实现前进、后退。
054.vue-router单页面应用的切换?
在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换。路由模块的本质 就是建立起url和页面之间的映射关系。
055.为什么不能用a标签?
至于为啥不能用a标签,这是因为用vue做的都是单页应用,就相当于只有一个主的index.html页面,所以你写的标签是不起作用的,必须使用vue-router来进行管理。
058.vue不能检测数组或对象变动问题的解决方法有哪些?
使用Proxy
使用立即执行函数