Vue 常见面试题 1、MVVM是什么?MVVM 与 MVC 的区别?它和其他框架(jquery)的区别是什么?哪些场景适合使用? 2、vue 与 angular 的区别?vue 与 react 的区别,使用场景分别是什么?vue 的优点和缺点?vue 全家桶开发?什么是 vue 渐进式开发? 3、什么是虚拟DOM?为什么使用虚拟DOM?虚拟DOM的优缺点?vue怎么操作dom?vue2.x 和 vue3.x 渲染器的 diff 算法分别说一下 4、Vue 的生命周期 5、Vue的模板编译原理,如何编译 template 模板? 6、批量异步更新策略、nextTick 原理及 vue.nextTick 有什么作用? 7、数据渲染有几种方式,有什么区别?v-html 会导致什么问题 8、v-if 和 v-show 有什么区别,切换时组件触发哪些什么周期钩子函数?适用于哪些场景? 9、v-if 和 v-for 为什么不建议混合使用? 10、key 主要是解决哪一类的问题(作用),为什么不建议用索引 i

Vue 常见面试题
1、MVVM是什么?MVVM 与 MVC 的区别?它和其他框架(jquery)的区别是什么?哪些场景适合使用?
2、vue 与 angular 的区别?vue 与 react 的区别,使用场景分别是什么?vue 的优点和缺点?vue 全家桶开发?什么是 vue 渐进式开发?
3、什么是虚拟DOM?为什么使用虚拟DOM?虚拟DOM的优缺点?vue怎么操作dom?vue2.x 和 vue3.x 渲染器的 diff 算法分别说一下
4、Vue 的生命周期
5、Vue的模板编译原理,如何编译 template 模板?
6、批量异步更新策略、nextTick 原理及 vue.nextTick 有什么作用?
7、数据渲染有几种方式,有什么区别?v-html 会导致什么问题
8、v-if 和 v-show 有什么区别,切换时组件触发哪些什么周期钩子函数?适用于哪些场景?
9、v-if 和 v-for 为什么不建议混合使用?
10、key 主要是解决哪一类的问题(作用),为什么不建议用索引 i

MVVM 是 Model-View-ViewModel 的缩写。

Model(模型层)代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。(axios data vuex(state))

View (视图层)代表UI组件,它负责将数据模型转化成UI展现出来。(template < /template>)

ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。(viewmodel是双向绑定实现的机制)

MVVM MVC 的区别:

MVC 模型视图控制器,视图是可以直接访问模型,所以,视图里面会包含模型信息,mvc 关注的是模型不变,所以,在 mvc 中,模型不依赖视图,但是视图依赖模型。

MVVM 模型 视图和 VM,VM 是作为模型和视图的桥梁,当模型层数据改变,VM 会检测到并通知视图层进行相应的修改。

它和其他框架区别:MVVM 是通过数据来显示视图;jquery 是通过节点来操作的。

适用场景:适用于数据操作比较多的场景。

     在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。  ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

 

2、vue 与 angular 的区别?vue 与 react 的区别,使用场景分别是什么?vue 的优点和缺点?vue 全家桶开发?什么是 vue 渐进式开发?

1、与AngularJS的区别

相同点:都支持指令:内置指令和自定义指令;都支持过滤器:内置过滤器和自定义过滤器;都支持双向数据绑定;都不支持低端浏览器。

不同点:AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观;在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢;Vue.js使用基于依赖追踪的观察并且使用异步队列更新,所有的数据都是独立触发的。

2、与React的区别

相同点: 都有自己的脚手架工具;支持项目工程化;都是数据驱动视图的框架; 中心思想相同:一切都是组件,组件实例之间可以嵌套;都提供合理的钩子函数,可以让开发者定制化地去处理需求;都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载;在组件开发中都支持mixins的特性。

不同点: React 采用的 Virtual DOM 会对渲染出来的结果做脏检查。 Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作 DOM。 React:数据单向流,语法-jsx,在 React 中需要使用 setState() 方法去更新状态。 Vue:数据双向绑定,语法-HTML,state 对象并不是必须的,数据由 data 属性在 Vue 对象中进行管理。

 

优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。

缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。

vue 全家桶开发:指的是:vue-router,vuex, vue-resource

渐进式:引入 vue.js 部分功能,逐渐取代之前的原生js、jquery。

3、什么是虚拟DOM?为什么使用虚拟DOM?虚拟DOM的优缺点?vue怎么操作dom?vue2.x 和 vue3.x 渲染器的 diff 算法分别说一下

什么是虚拟DOM

用 js 模拟一颗 dom 树,放在浏览器内存中,当你要变更时,虚拟 dom 使用 diff  算法进行新旧虚拟 dom 的比较,将变更放到变更队列中,反应到实际的dom树,减少了dom操作。 虚拟 DOM 将 DOM 树转换成一个 JS 对象树,diff 算法逐层比较、删除、添加操作;但是,如果有多个相同的元素,可能会浪费性能,所以,react 和 vue-for 引入 key 值进行区分。(让我们不用直接操作DOM元素,只操作数据便可以重新渲染页面)

为什么使用虚拟DOM

 1、手动操作DOM比较麻烦,还需要考虑浏览器兼容性问题,虽然有jQuery等库简化DOM操作,但是随着项目的复杂DOM操作复杂提升

 2、为了简化DOM的复杂操作于是出现了各种MVVM框架,MVVM框架解决了视图和状态的同步问题

3、为了简化视图的操作我们可以使用模板引擎,但是模板引擎没有解决跟踪状态变化的问题,于是Virtual DOM出现了. Vitual DOM的好处是当状态改变时不需要立即更新DOM,只需要创建一个虚拟树来描述DOM, Virtual DOM内部将弄清楚如何有效(if)的更新DOM

优点:

1、维护视图和状态的关系

2、复杂视图情况下提升渲染性能 3、除了渲染DOM以外,还可以实现SSR(Nuxt.js/Next.js)、 原生应用(Weex/React Native)、 小程序(mpvue/uni-app)等

4、虚拟DOM具有批处理和高效的Diff算法,最终表现在DOM上的修改只是变更的部分,可以保证非常高效的渲染,优化性能.

缺点:

首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。

vue怎么操作dom 设置:ref=’name’ 使用:this.$refs.name

diff 算法

diff算法比较新旧虚拟 dom 的过程:

如果节点类型相同,则比较数据,修改数据;

如果节点不同,直接干掉节点及所有子节点,插入新的节点;

如果给每个节点都设置了唯一的key,就可以准确的找到需要改变的内容,否则就会出现修改一个地方导致其他地方都改变的情况。

比如A-B-C-D, 我要插入新节点A-B-M-C-D,实际上改变的了C和D。但是设置了key,就可以准确的找到B C并插入

正常diff两个树的时间复杂度是0(n^3),但实际情况下我们很少会进行跨层级的移动DOM,所以vue将Diff进行了优化,从o(n^3)->0(n),只有当新旧 children都为多个子节点时才需要用核心的diff算法进行同层级比较。

Vue2的核心diff算法采用了双端比较的算法,同时从新旧 children的两端开始进行比较,借助key值找到可复用的节点,再进行相关操作。相比React的diff算法,同样情况下可以减少移动节点次数,减少不必要的性能损耗,更加的优雅。

Vue3.x借鉴了算法 ivi和 inferno算法 在创建VNode时就确定其类型,以及在 mount/ patch的过程中采用位运算来判断一个VNode的类型,在这个基础之上再配合核心的diff算法,使得性能上较Vue2.x有了提升。(实际的实现可以结合vue3x源码看。)

虚拟dom的作用:虚拟dom是为了解决浏览器性能问题而被设计出来的;当操作数据时,将改变的dom元素缓存起来,都计算完后再通过比较映射到真实的dom树上

4、Vue 的生命周期

创建前 beforeCreate 在数据观测和初始化事件还未开始

创建后 created: 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来

载入前 beforeMount: 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。

载入后 mounted:在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。

更新前 beforeUpdate: 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。

更新后 updated: 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。

销毁前 beforeDestroy: 在实例销毁之前调用。实例仍然完全可用。

销毁后 destroyed:在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。

什么是 vue 生命周期?

Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。

vue 生命周期的作用是什么?

它的生命周期中有多个事件钩子,让我们在控制整个 Vue 实例的过程时更容易形成好的逻辑。

vue 生命周期总共有几个阶段?

它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后。

第一次页面加载会触发哪几个钩子?

 会触发这几个钩子: beforeCreate、created、beforeMount 和 mounted 。

DOM 渲染在哪个周期中就已经完成? DOM 渲染在 mounted 中就已经完成了。

vue 中生命周期钩子函数有哪些,请写出语法

 创建前beforeCreate 创建后created、挂载前beforeMount 挂载后mounted、更新前beforeUpdate 更新后updated、销毁前beforeDestroy 销毁后destroyed、激活activated 未激活deactivated 未激活是啥

什么时候触发激活和未激活生命周期钩子函数

当页面或者组件被缓存则激活 activated,未激活 deactivated 会取代创建和销毁

挂载和创建之间的区别

创建之后只可以访问数据不可以操作dom 挂载之后可以访问数据可以操作dom

5、Vue的模板编译原理,如何编译 template 模板?

vue模板的编译过程分为3个阶段:

 第一步是将 模板字符串 转换成 element ASTs(解析器) 解析将模板字符串解析生成AST,生成的AST元素节点总共有3种类型,1为普通元素,2为表达式,3为纯文本

第二步是对 AST 进行静态节点标记,主要用来做虚拟DOM的渲染优化(优化器) vue模板中井不是所有数据都是响应式的,有很多数据是首次染后就永远不会变化的,那么这部分数据生成的DOM也不会变化,我们可以在 patch的过程跳过对他们的比对 此阶段会深度遍历生成的AST树,检测它的每一颗子树是不是静态节点,如果是静态节点则它们生成DOM永远不需要改变,这对运行时对模板的更新起到极大的优化作用。

第三步是使用 element ASTs 生成 render 函数代码字符串(代码生成器) 生成代码:const code = generate(ast, options );通过 generate 方法,将 ast 生成 render 函数

6、批量异步更新策略、nextTick 原理及 vue.nextTick 有什么作用?

(1)批量异步策略 Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。

(2)nextTick 在下次DOM更新循环结束后执行延迟回调,在修改数据之后立即使用 nextTick 来获取更新后的DOM。 数据更新是一个异步操作异步 dom,更新后使用 vue.nextTick 可以立即得到更新后的数据

nextTick 对于 microtask 的实现,会先检测是否支持 Promise,不支持的话,直接指向 macrotask,而 macrotask的实现,优先检测是否支持 setTinmediat。(高版本IE和 Etage支持),不支持的再去检测是否支持 MessageChannel,如果仍不支持,最终降级为 setTimeout 0;默认的情况,会先以 microtask 方式执行,因为 microtask 可以在一次 tick 中全部执行完毕,在一些有重绘和动画的场景有更好的性能。

但是由于 microtask 优先级较高,在某些情况下,可能会在事件冒泡过程中触发,导致一些问题,所以有些地方会强制使用 macrotask(如v-on)。

 注意:之所以将 nextTick 的回调函数放入到数组中一次性执行,而不是直接在 nextTick 中执行回调函数,是为了保证在同一个 tick 内多次执行了 nextTick,不会开启多个异步任务,而是把这些异步任务都压成一个同步任务,在下一个tick内执行完毕。

7、数据渲染有几种方式,有什么区别?v-html 会导致什么问题

插值表达式:{{}} 只会替换自己的这个占位符,不会把整个元素的内容清空

v-html:只有v-html可以渲染HTML代码,会覆盖元素中原本的内容(相当于原生js中的innerHTML) 在网站上动态渲染任意HTML,很容易导致XSS攻击。所以只能在可信内容上使用v-html,且永远不能用于用户提交的内容上。

v-text:完整地输出内容而不会转换标签

闪烁:使用插值表达式 {{}},会造成界面闪烁。

解决方式:

使用 v-text

使用 v-cloak 指令,v-cloak 指令和 css 规则如 [v-cloak]{display:none} 一起用

8、v-if 和 v-show 有什么区别,切换时组件触发哪些什么周期钩子函数?适用于哪些场景?

区别:

 v-if 控制的是 dom 的销毁和创建

v-show 只是控制 dom 的css中 display属性

 

触发的生命周期:

 v-if 显示、创建、挂载、隐藏和销毁

 v-show 显示隐藏不触发生命周期钩子函数

使用场景:

 v-if 切换的开销更大,而 v-show 初始化渲染开销更大,在需要频繁切换或者切换的部分 dom 很复杂时,使用 v-show 更合适;渲染后很少切换的则使用 v-if 更合适。

9、v-if 和 v-for 为什么不建议混合使用?

原因:被渲染的 dom 会重复一个创建销毁的过程

解决方法:

使用计算属性 过滤数据

 computed:{  showList:function(){  return this.list.filter(var,index)=>{  return var.isshow  }  } }

当 v-for 和 v-if 处于同一个节点时,v-for的优先级比v-if更高,这意味着v-if将分别重复运行于每个v-for循环中,如果要遍历的数组很大,而真正要展示的数据很少时,这将造成很大的性能浪费。这种场景建议使用 computed,先对数据进行过滤。

10、key 主要是解决哪一类的问题(作用),为什么不建议用索引 index(重绘)

(1)key 的作用主要是为了高效的更新虚拟 DOM

(2)当以 index 为 key 值时,如果数组长度发生变化,会导致 key 的变化,比如删除其中某一项,那么 index 会相应变化。 所以用 index作为key和不加index没有什么区别,都不能提升性能。一般用每项数据的唯一值来作为key,就算数组长度变化,也不会影响到这个key

11、v-on 可以监听多个方法吗?怎么实现?

可以一次性绑定多个事件,写在对象中即可。

实现:

<button v-on="{mouseenter:onEnter, mouseleave:onLeave">鼠标进来1</button>
<button @mouseenter="onEnter", @mouseleave="onLeave">鼠标进来2</button>

一个事件绑定多个函数,按顺序执行,这里的分隔函数可以用逗号也可以用分号
<button @click="a(), b()">点我ab</button>
<button @click="one()">点我one</button>

 

12、vue 实现双向数据绑定的原理是什么?你用过哪些 v-model 修饰符?

当一个vue实例创建后vue会遍历data选项的属性,用object.definproperty将它转化为getter或者setter,并且内部追踪相关依赖,在属性访问和修改时通知变化每一个组件实例化都有相应的watcher程序实例,他会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时会通知watcher重新计算,从而使得它相关的组件的以更新

Vue实现数据双向绑定的原理:Object.defineProperty()

vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。

vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。

修饰符:

.lazy文本框失去焦点后在更新数据  

.trim清除前后空格的  

.number从字符中获取数字

v- model 是如何实现双向绑定的?

vue 2.0:v-model是用来在表单控件或者组件上创建双向绑定的,他的本质是v-bind和v-on的语法糖,在个组件上使用v-mode1,默认会为组件绑定名为 value的prop和名为 input的事件。

 Vue3.0:在3X中,自定义组件上的v-mode1相当于传递了 modelValue prop并接收抛出的update: modelValue事件

13、计算属性和实例方法有什么区别、computed 和 watch 有什么区别? 什么是 vue 的计算属性,computed 是如何实现的?vue 怎么监听数据的变化,怎么监听一个对象属性的变化?

计算属性和实例方法有什么区别(computed,methods )

实例方法指的是对象能调用的函数,对象里所有可以调用的函数全叫实例方法。

答:计算属性有缓存,实例方法没有缓存 计算属性调用时 total 不可以传参 实例方法调用时 total()可以传参

computed 和 watch 的区别:

computed  1、computed是计算属性,也就是依赖某个值或者props通过计算得来得数据;  2、 computed的值是在getter执行之后进行缓存的,只有在它依赖的数据发生变化,会重新调用getter来计算;  3、 不支持异步,当computed内有异步操作时无效,无法监听数据的变化;

watch 1、watch是监听器,可以监听某一个数据,然后执行相应的操作; 2、不支持缓存,数据变直接会触发相应的操作; 3、监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值; 4、支持异步操作;

什么时候用computed 什么时候用watch 比较合适?

当多个属性影响一个属性的时候,建议用computed(computed适合在模板渲染中,某个值是依赖了其他的响应式对象甚至是计算属性计算而来)

当一个值发生变化之后,会引起一系列的操作,这种情况就适合用watch(watch适合监听某个值的变化去完成一段复杂的业务逻辑)

vue 的计算属性:

在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。

好处:①使得数据处理结构清晰;②依赖于数据,数据更新,处理结果自动更新;③计算属性内部this指向vm实例;④在template调用时,直接写计算属性名即可;⑤常用的是getter方法,获取数据,也可以使用set方法改变数据;⑥相较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候computed从缓存中获取,不会重新计算。

computed 的实现:

流程总结如下:

1、当组件初始化的时候, computed和data会分别建立各自的响应系统, Observer遍历data中每个属性设置get/set数据拦截

2、初始化 computed会调用 initComputed 函数

2.1、注册一个 watcher实例,并在内实例化一个Dep消息订阅器用作后续收集依赖(比如渲染函数的 watcher或者其他观察该计算属性变化的 watcher) 2.2、调用计算属性时会触发其 Object.defimeProperty的get访问器函数

2.3、调用 watcher.depend()方法向自身的消息订间器dep的subs中添加其他属性的watcher

2.4、调用 watcher的 evaluate方法(进而调用 watcher的get方法)让自身成为其他watcher的消息订阅器的订阅者,首先将 watcher赋给dep.target,然后执行 getter求值函数,当访问求值函数里面的属性(比如来自data、prope或其他 computed)时,会同样触发它们的get访问器函数从而将该计算属性的 watcher添加到求值函数中属性的watcher的消息订阅器dep中,当这些操作完成,最后关闭dep.target赋为 null 并返回求值函数结果

3、当某个属性发生变化,触发set拦截函数,然后调用自身消息订阅器dep的 notify方法,遍历当前dep中保存着所有订阅者 wather的subs数组,并逐个调用 watcher的 update方法,完成响应更新

vue 怎么监听数据的变化,怎么监听一个对象属性的变化

用 watch 监听数据的变化 监听对象属性,先在 computed 中声明中间件: computed:{  newage:function(){  return this.person.age  } } watch:{  num:function(newdata,olddata){  console.log(newdata,olddata)  },  newage:function(){  console.log("生日快乐!")  } }

 

14、vue 的父组件和子组件生命周期钩子执行顺序是什么?

渲染过程

 父组件挂载完成一定是等子组件都挂载完成后,才算是父组件挂载完,所以父组件的 mounted在子组件 mouted之后

父beforeCreate → 父created → 父beforeMount → 子beforeCreate → 子created →子 beforeMount →子mounted->父 mounted

子组件更新过程:

 1.影响到父组件:父 beforeUpdate→>子 beforeUpdate->子 updated->父 updated

2.不影响父组件:子 beforeUpdate>子 updated

父组件更新过程:

 1.影响到子组件:父 beforeUpdate→>子 beforeUpdate->子 updated->父 updated

2.不影响子组件:父 beforeUpdate→>父 updated

销毁过程:

父 beforeDestroy → 子 beforeDestroy → 子 destroyed → 父 destroyed

不管是哪种情况,都一定是父组件等待子组件完成后,才会执行自己对应完成的钩子。

15、Vue2.0 组件通信方式有哪些? vue 父子组件怎样实现通讯?vue 组件的参数传递,vue 中子组件调用父组件的方法?vue 中怎么实现组件之间的嵌套?

1、父子组件通信

 props 和 event、v-model、.sync、ref、$parent 和 $children、$emit

2、 非父子组件

$attr 和 $listeners 、provide 和 inject、eventBus、通过实例 $root 访问、vuex、dispath 和 brodcast

实现通讯:

 父传子:父组件:<mydiv :list='list'> </mydiv>      子组件:props[‘list’]

子传父:子组件:this.$emit(‘子组件事件名’,参数)   父组件:<mydiv @子组件事件名=‘父组件事件名’>

参数传递:

1、父组件与子组件传值

父组件传给子组件:子组件通过props方法接受数据;

子组件传给父组件:$emit方法传递参数

2、非父子组件间的数据传递,兄弟组件传值 eventBus,

就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。兄弟组件可以父传子 子传父;Vuex也可以实现数据共享 项目比较小时,用这个比较合适。(虽然也有不少人推荐直接用VUEX,具体来说看需求咯。技术只是手段,目的达到才是王道。)

子组件调父组件的方法:

第一种方法是直接在子组件中通过 this.$parent.event 来调用父组件的方法

第二种方法是在子组件里用 $emit 向父组件触发一个事件,父组件监听这个事件。

第三种是父组件把方法传入子组件中,在子组件里直接调用这个方法

16、怎样使用 props 限定传递的数据,有哪些属性?非 props 属性有什么特点?如何解决 props 层级过深的问题?

props 限定传递的数据

type //限定传递的数据类型

 Required:true false //是否必传

 Default:false //指定默认值

Validator:function(){ //自定义规则 }

非 props 属性的特点:

①会显示在解析之后的标签上 ②子组件不能使用该属性

解决props层级过深:

(1)使用vuex

(2)传递数据,使用以下接收(均不含被props接收的数据) this.$attrs 接收属性 this.$listeners 接收事件(不含被 .native 修饰符的事件)

组件之间的嵌套:组件之间的嵌套使用,可以借助插槽,让插槽接受子组件中的内容

17、如果子组件直接修改父组件的值会发生什么?怎么解决,要修改多个数据怎么办?解释 VUE 中单向数据流的概念?

如果修改的不是引用类型的值时会报错,告诉我们不能直接修改父组件的值。

 (1)可以使用.sync修饰符来修改值,对一个 prop 进行“双向绑定”。(注意.sync 修饰符的 v-bind 不能和表达式一起使用)

 (2)父组件将改变值的方法传递给子组件

单向数据流的概念: 子组件不可以直接修改父组件传过来的参数,如果直接修改会报错,只能声明成自己的才可以修改

18、怎样声明全局组件,怎样使用全局组件?怎样声明局部组件,怎样使用局部组件?

声明全局组件: vue.component(‘myheader’,{ Template:<div>全局组件</div> })

使用全局组件: <myheader></myheader>

声明局部: 声明成 ***.vue文件中模板在中。

使用局部组件:

 Js模块化导出 <script></script>

css 定义 <style scoped></style>

 import 引入,注册 components 调用

 

19、多个组件之间如何拆分各自的 state,每块小的组件有自己的状态,它们之间还有一些公共的状态需要维护,如何思考这块?

(1)公共的数据部分可以提升至和他们最近的父组件,由父组件派发

(2)公共数据可以放到vuex中统一管理,各组件分别获取

20、vue 中如何编写可复用的组件?

(1)以组件功能命名

(2)只负责ui的展示和交互动画,不要在组件里与服务器打交道(获取异步数据等)

(3)可复用组件不会因组件使用的位置、场景而变化。尽量减少对外部条件的依赖。

21、vue 组件中的 data 为什么必须是一个函数?vue中组件 data 为什么是 return ー个对象的函数,而不是直接是个对象?

函数:

对象为引用类型,当重用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改;而使用返回对象的函数,由于每次返回的都是一个新对象(Object的实例),引用地址不同,则不会出现这个问题。

对象:

当data定义为对象后,这就表示所有的组件实例共用了一份data数据,因此,无论在哪个组件实例中修改了data,都会影响到所有的组件实例。组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据;而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。

22、什么是插槽,怎么使用,什么是具名插槽,如何使用?什么是作用域插槽?

插槽,也就是slot,是组件的一块 HTML 模板,这块模板显示不显示、以及怎样显示由父组件来决定。

 由于插槽是一块模板,所以,对于任何一个组件,从模板种类的角度来分,其实都可以分为非插槽模板和插槽模板两大类。 非插槽模板指的是 html 模板,比如‘div、span、ul、table’这些;非插槽模板的显示与隐藏以及怎样显示由组件自身控制;插槽模板是 slot,它是一个空壳子,因为它的显示与隐藏以及最后用什么样的html模板显示由父组件控制;但是插槽显示的位置却由子组件自身决定,slot 写在组件 template 的什么位置,父组件传过来的模板将来就显示在什么位置。

目的:内容不确定,以后谁来调用记得填

设计思路:子组件定义插槽,父组件提供内容去填补插槽

单个插槽 | 默认插槽 | 匿名插槽

单个插槽是 vue 的官方叫法,但是其实也可以叫它默认插槽,或者与具名插槽相对,我们可以叫它匿名插槽。因为它不用设置name属性。

 单个插槽可以放置在组件的任意位置,但是就像它的名字一样,一个组件中只能有一个该类插槽。相对应的,具名插槽就可以有很多个,只要名字(name属性)不同就可以了。

使用:

父组件:在 <template></template>  里面任意写入 HTML 代码

子组件:在需要展示的位置放置  即可展示

具名插槽

匿名插槽没有 name 属性,所以是匿名插槽,那么,插槽加了 name 属性,就变成了具名插槽。

具名插槽可以在一个组件中出现 N 次,出现在不同的位置。

作用域插槽 | 带数据的插槽

官方叫它作用域插槽,实际上,对比前面两种插槽,我们可以叫它带数据的插槽。什么意思呢,就是前面两种,都是在组件的template里面写;但是作用域插槽要求,在slot上面绑定数据。 插槽获取子组件的数据 需要属性传递 结合作用域插槽语法,代码如下 设置:Slot-scope=‘自定义名字’ 使用: 自定义名字     {{scope}}

作用域插槽跟单个插槽和具名插槽的区别:

因为单个插槽和具名插槽不绑定数据,所以父组件提供的模板一般要既包括样式又包括内容,而作用域插槽,父组件只需要提供一套样式(在确实用作用域插槽绑定的数据的前提下)。

23、对 keep-alive 的了解?keep-alive 组件有什么作用?keep-alive 组件有哪些属性?

理解:每次切换界面组件都会重新初始化,离开页面就会集体销毁;keep-alive是用来保活,相当于缓存,即使你离开页面,组件也不销毁

keep-alive本身注册了全局,而且不参与离开销毁等生命周期,组件写在他的里面,自然不受外界影响;正常切换组件的时候,都会通知子组件,生命周期结束了,然后每个组件都冒泡调用销毁;而keep-alive组件直接就不执行销毁,也不通知子组件销毁,下次进入组件还可以组件复用

keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。

在vue 2.1.0 版本之后,keep-alive新加入了两个属性: include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。

使用方法:   

<keep-alive include='include_components' exclude='exclude_components'>
    <component>

        <!-- 该组件是否缓存取决于include和exclude属性 -->

    </component>
</keep-alive>   

  

参数解释:

 include - 字符串或正则表达式,只有名称匹配的组件会被缓存

 exclude - 字符串或正则表达式,任何名称匹配的组件都不会被缓存 include 和 exclude 的属性允许组件有条件地缓存。二者都可以用“,”分隔字符串、正则表达式、数组。当使用正则或者是数组时,要记得使用 v-bind 。

作用:缓存组件缓存页面(router-view)

属性:include 声明需要被缓存的组件页面 exclude 声明不需要被缓存的组件页面

使用场景:商品分类页面(每次进入会发ajax,这根本没有必要,直接保活keep-alive就相当于缓存,保持活着的状态,避免反复的销毁创建)等等

24、如何自定义事件?你知道哪些事件修饰符?什么是 vue 全局事件解绑?

自定义事件:

每个Vue创建的实例都会出现一个事件接口:var vm = new Vue({el: '#app'})

自定义事件的定义(发布):vm.$on(自定义事件的名称,自定义事件的事件处理程序) vm.$on( 'aa', function () {console.log( 'aa' )})

自定义事件的触发 ( 订阅 ):vm.$emit( 自定义事件的名称,自定义事件处理程序需要的参数1,参数2,参数3) vm.$emit( 'aa' )

事件修饰符:

.stop 阻止事件冒泡    .once 只执行一次,一次性事件  .self 阻止事件冒泡和事件捕获

.captrue 事件捕获阶段触发   .prevent 阻止浏览器默认行为   .native 触发原生事件

vue 全局事件解绑:

在vue中,写在 methods 里面的方法,在页面切换时一般就自动销毁了,但是写在 window 上的事件,需要我们手动解绑,这也是为了提高代码执行效率,使用生命周期函数 destroy,在页面离开时执行解绑。

(例子看文件)

25、vue中常用的指令有哪些?vue 中如何自定义指令(全局和局部)?自定义指令接受哪些生命钩子函数?

vue中常用的指令:

V-text:主要用来更新textContent,可以等同于JS的text属性

V-html:双大括号的方式会将数据解释为纯文本,而非HTML。为了输出真正的HTML,可以用v-html指令。它等同于JS的innerHtml属性。

V-show:用于根据条件展示元素。

V-if可以实现条件渲染,Vue会根据表达式的值的真假条件来渲染元素。 V-else-if:充当v-if的else-if块,可以链式的使用多次。可以更加方便的实现switch语句。

V-else:是搭配v-if使用的,它必须紧跟在v-if或者v-else-if后面,否则不起作用。

V-on:主要用来监听dom事件,以便执行一些代码块。表达式可以是一个方法名。

V-bind:用来动态的绑定一个或者多个特性。没有参数时,可以绑定到一个包含键值对的对象。常用于动态绑定class和style。以及href等。

v-for用v-for指令根据遍历数组来进行渲染

V-model这个指令用于在表单上创建双向数据绑定

V-slot

V-pre:主要用来跳过这个元素和它的子元素编译过程。可以用来显示原始的Mustache标签。跳过大量没有指令的节点加快编译。

V-cloak:这个指令是用来保持在元素上直到关联实例结束时进行编译。

V-once:v-once关联的实例,只会渲染一次。之后的重新渲染,实例极其所有的子节点将被视为静态内容跳过,这可以用于优化更新性能。

 

自定义全局指令:

Vue.directive('color', function(obj,arg){  //obj,第一个参数,指令调用位置的 dom 对象  //arg,指令对象,和指令相关的信息  obj.style.backgroundColor=arg.value })

自定义局部指令:

directive: {  color: function(obj,arg){  //obj,第一个参数,指令调用位置的 dom 对象  //arg,指令对象,和指令相关的信息  obj.style.backgroundColor=arg.value  } }

生命钩子函数:

directive: {
 color: { 
  bind: function(){  // 指令绑定给 dom 元素时触发  console.log('bind')  }, 
  inserted: function(){  // 虚拟 dom 插入时触发  console.log('inserted')  }, 
  update: function(){  // 传参更新时触发  console.log('update')  },
  unbind: function(){  // 指令解除绑定时触发  console.log('unbind')  }  }
}

26、如何声明一个过滤器(全局和局部)?你常用的自定义过滤器有哪些?

过滤器:用于一些常见的文本格式化。

全局过滤器:

 vue.filter(‘gettime’,function(date){ 

Var time=new date(date) 

return time.getFullyear()+’/’+time.getMonth()+1’/’+getDate() }

)

局部过滤器:

 Filters:{  Gettime(date){

  Var time=new date(date)  Return time.getFullyear()+’/’+time.getMonth()+1’/’+getDate()  }

 }

常用的自定义过滤器:

(1)   去除空格、(2)时间转换、(3)大小写转换、(4)字符串替换、

(5)金额字符转金额/数字转金额字符、(6)保留两位小数、(7)判断字符串长度并省略

根据自己常用的来说。

 

27、完整的 vue-router 导航解析流程

(1)导航被触发。

(2)在失活的组件里调用离开守卫。

(3)调用全局的 beforeEach 守卫。

(4)在重用的组件里调用 beforeRouteUpdate 守卫

(5)在路由配置里调用 beforeEnter。

(6)解析异步路由组件。

(7)在被激活的组件里调用 beforeRouteEnter。

(8)调用全局的 beforeResolve 守卫

(9)导航被确认。

(10)调用全局的 afterEach 钩子。

(11)触发 DOM 更新。

(12)用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。

28、vue 路由的钩子函数

vue-router一共给我们提供了三大类钩子函数来实现路由守卫:

 1、全局钩子函数(beforeEach、afterEach)

 2、路由独享的钩子函数(beforeEnter)

 3、组件内钩子函数(beforeRouterEnter、beforeRouterUpdate、beforeRouterLeave)

29、vue-router路由的两种模式?如何实现?有什么区别?如何定义 vue-router 的动态路由? 怎么获取传过来的值?

vue-router中默认使用的是hash模式

(1)hash模式

 http://localhost:8080/#/pageA     hash 的值为 #/pageA

 在浏览器中符号“#”,# 以及 # 后面的字符称之为hash,用window.location.hash读取。

 改变hash,浏览器本身不会有任何请求服务器动作的,但是页面状态和url已经关联起来了。

后面hash值的变化,不会导致浏览器向服务器发出请求,浏览器不发出请求,就不会刷新页面;同时通过监听 hashchange事件可以知道hash发生了哪些变化,然后根据hash变化来实现更新页面部分内容的操作。

特点:

hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。

hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。

(2)history模式

 http://localhost:8080/ 正常的路径,并没有#

history模式的实现,主要是HTML5标准发布的两个API, pushState和replaceState,这两个API可以改变url,但是不会发送请求。这样就可以监听url变化来实现更新页面部分内容的操作。

 history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。

 history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如:http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。

区别:

(1 )在 url 显示: hash 有 # ; history 无 # 对 seo 比较友好

(2)刷新页面时: hash 可以加载到hash值对应页面; history 没有处理的话,会返回404,一般需要后端将所有页面都配置重定向到首页路由

(3 )兼容性: hash 支持低版本浏览器和IE浏览器 ; history (HTML5新推出的API)不支持ie低版本

定义:在 router 目录下的 index.js 文件中,对 path 属性加上 /,后面是跳转的地址

获取传过来的值:在 router 目录下的 index.js 文件中,对 path 属性加上 /:id,使用 router 对象的 params.id 获取。

30、路由显示区域和路由跳转分别是哪个组件?$route 和 $router 有什么区别? 路由懒加载怎么实现,有什么意义?

显示:router-view      跳转 router-link

 

$route 和 $router 的区别:

$route是路由信息对象”,包括path, params, hash, query, matched, name 等路由信息参数。

$router是“路由实例"对象包括了路由的跳转方法,钩子函数等

 

路由懒加载的实现:let Addclass = resolve =>require([' @/views/ Addclass' ] ,resolve )

 路由懒加载的意义:为给客户更好的客户体验,首屏组件加载速度更快一些,解决白屏问题。

31、vue-router的几种实例方法以及参数传递?

vue-router传递参数分为两大类:

(1)编程式的导航 router.push

(2)声明式的导航 <router-link></router-link>

 

传递参数的方式:

编程式导航传递参数有两种类型:字符串、对象。

声明式的导航和编程式的导航传递参数的方式一样

路由传递参数和传统传递参数是一样的,命名路由类似表单提交而查询就是url传递,(在vue项目中基本上掌握了这两种传递参数就能应付大部分应用了)

总结:

 1.命名路由搭配params,刷新页面参数会丢失

2.查询参数搭配query,刷新页面数据不会丢失

 3.接受参数使用this.$router后面就是搭配路由的名称就能获取到参数的值

32、router的meta有什么用?怎样给路由添加 active-class?

meta 的作用:在meta对象中可以设置一些状态,通常设置标题或是否需要缓存。

路由添加 active-class 配置文件中linkActiveClass 默认的是router- link- active 可以直接在标签中使用active-class

33、vue2.x 的响应式原理?vue3.x响应式原理?

vue2.x 的响应式原理:

vue的响应式是通过 Object.defineProperty 对数据进行动持,并结合观察者模式实现。 vue 利用 object.detineProperty 创建一个 observe 来劫持监听所有的属性,把这些属性全部转为 getter 和 setter。Vue 中每个组件实例都会对应一个 watcher 实例,它会在组件渲染的过程中把使用过的数据属性通过 getter 收集为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

Object.defineProperty有哪些缺点?(无法检测到对象属性的新增或删除)

 1、Object.defineProperty只能劫持对象的属性,而 Proxy 是直接代理对象 由于 Object.defineProperty只能对属性进行劫持,需要遍历对象的每个属性,而 Proxy可以直接代理对象。

2、Object.defineProperty 对新增属性需要手动进行 observe,由于Object.defineProperty劫持的是对象的属性,所以新增属性时,需要重新遍历对象,对其新增属性再使用 Object.defineProperty 进行劫持,也正是因为这个原因,使用 vue 给 data 中的数组或对象新增属性时,需要使用vm.$set才能保证新增的属性也是响应式的

3、Proxy支持13种拦截操作,这是 defineProperty 所不具有的。

 4、新标准性能红利 Proxy 作为新标准,长远来看,JS引擎会继续优化 Proxy,但 getter 和 setter 基本不会再有针对性优化 5、Proxy 兼容性差目前并没有一个完整支持 Proxy 所有拦截方法的 Polyfill 方案

vue3.x响应式原理:

         vue3.x改用 Proxy 替代 object.defineProperty。因为 Proxy 可以直接监听对象和数组的变化,并且有多达13种拦截方法。井且作为新标准将受到浏览器厂商重点持续的性能优化。

Poxy只会代理对象的第一层,那么vue3又是怎样处理这个问题的呢?

 判断当前 Reflect.get的返回值是否为 Object,如果是则再通过 reactive 方法做代理,这样就实现了深度观测。

监测数组的时候可能触发多次 get/set,那么如何防止触发多次呢? 我们可以判断key是否为当前被代理对象target自身属性,也可以判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行 trigger。

34、vuex 是什么?什么是“状态管理模式”?vuex 有哪些核心的属性?Vuex 和单纯的全局对象有什么区别?

官方:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension (opens new window),提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

 简单的说:Vuex 是 vue 框架中状态管理。

状态管理模式:

把组件的共享状态抽取出来,以一个全局单例模式管理。在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为,这就是“状态管理模式”。 应用场景有:单页应用中,组件之间的数据状态。

应用实例:

1、购物车功能(数据的存储);

2、下单页面有选择优惠券按钮,点击进入优惠券页面,选择后返回到下单页,数据会绑定回来,显示已选择的优惠券;

3、登录状态(用户信息的存储);

4、音乐播放 等等

核心属性: state、mutations、getters、action 和 modules。

state:Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。

mutations:mutations定义的方法动态修改 Vuex 的 store 中的状态或数据。

getters:类似 vue 的计算属性,主要用来过滤一些数据。

 action:actions 可以理解为通过将 mutations 里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。

modules:项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

state => 基本数据(只用来读取的状态集中放在 store 中)

getters => 从基本数据派生的数据

mutations => 修改数据,同步(改变状态的方式是在 mutations 中)

actions => 修改数据,异步(异步逻辑应该封装在 action 中)

modules => 模块化Vuex

 

 

vuex和全局对象主要有两大区别:

1、vuex的状态存储是响应式的。当vue组件从 store中读取状态的时候,若 store中的状态发生变化,那么相应的组件也会相应地得到高效更新。

 2、不能直接改变 store中的状态。改变 store中的状态的唯一途径就是显式地提交( commit)mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

35、vue中proxy代理?

Vue 框架开发的时候,会遇到跨域的问题,可在config/index.js 里配置proxyTable内容,使用proxy代理。

proxyTable: {
    '/api': {
    target: 'http://xxx.com:8080', // 你要代理的域名和端口号,要加上http
    changeOrigin: true, // 跨域
    pathRewrite: {
    '^/api': '/api' // 这里用‘/api’代替target里面的地址,组件中调用接口时直接用api代替 比如我要调用'http://xxx.com:8080/api/NEWS/getNews.json?page=1&pageSize=10
    ',直接写‘/api/NEWS/getNews.json?page=1&pageSize=10’即可
    }
}

然后在axios请求中:
getNewsList() {
    const url = '/api/NEWS/getNews.json?page=1&pageSize=10'
    axios.get(url)
    .then((res) => {
        res = res.data
            if (res.state) {
            this.news = res.result
            }
    })
}

 

36、vue中对象更改检测的注意事项

由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除;

对于已经创建的实例,Vue 不能动态添加根级别的响应式属性;但是,可以使用 Vue.set(object, key, value)方法向嵌套对象添加响应式属性; 还可以使用 vm.$set实例方法添加,它只是全局Vue.set 的别名;

有时可能需要为已有对象赋予多个新属性,比如使用 Object.assign()或 _.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。

37、Vue.js 全局运行机制

Vue 常见面试题
1、MVVM是什么?MVVM 与 MVC 的区别?它和其他框架(jquery)的区别是什么?哪些场景适合使用?
2、vue 与 angular 的区别?vue 与 react 的区别,使用场景分别是什么?vue 的优点和缺点?vue 全家桶开发?什么是 vue 渐进式开发?
3、什么是虚拟DOM?为什么使用虚拟DOM?虚拟DOM的优缺点?vue怎么操作dom?vue2.x 和 vue3.x 渲染器的 diff 算法分别说一下
4、Vue 的生命周期
5、Vue的模板编译原理,如何编译 template 模板?
6、批量异步更新策略、nextTick 原理及 vue.nextTick 有什么作用?
7、数据渲染有几种方式,有什么区别?v-html 会导致什么问题
8、v-if 和 v-show 有什么区别,切换时组件触发哪些什么周期钩子函数?适用于哪些场景?
9、v-if 和 v-for 为什么不建议混合使用?
10、key 主要是解决哪一类的问题(作用),为什么不建议用索引 index(重绘)
11、v-on 可以监听多个方法吗?怎么实现?
12、vue 实现双向数据绑定的原理是什么?你用过哪些 v-model 修饰符?
13、计算属性和实例方法有什么区别、computed 和 watch 有什么区别? 什么是 vue 的计算属性,computed 是如何实现的?vue 怎么监听数据的变化,怎么监听一个对象属性的变化?
 
14、vue 的父组件和子组件生命周期钩子执行顺序是什么?
15、Vue2.0 组件通信方式有哪些? vue 父子组件怎样实现通讯?vue 组件的参数传递,vue 中子组件调用父组件的方法?vue 中怎么实现组件之间的嵌套?
16、怎样使用 props 限定传递的数据,有哪些属性?非 props 属性有什么特点?如何解决 props 层级过深的问题?
17、如果子组件直接修改父组件的值会发生什么?怎么解决,要修改多个数据怎么办?解释 VUE 中单向数据流的概念?
18、怎样声明全局组件,怎样使用全局组件?怎样声明局部组件,怎样使用局部组件?
 
19、多个组件之间如何拆分各自的 state,每块小的组件有自己的状态,它们之间还有一些公共的状态需要维护,如何思考这块?
20、vue 中如何编写可复用的组件?
21、vue 组件中的 data 为什么必须是一个函数?vue中组件 data 为什么是 return ー个对象的函数,而不是直接是个对象?
22、什么是插槽,怎么使用,什么是具名插槽,如何使用?什么是作用域插槽?
23、对 keep-alive 的了解?keep-alive 组件有什么作用?keep-alive 组件有哪些属性?
24、如何自定义事件?你知道哪些事件修饰符?什么是 vue 全局事件解绑?
25、vue中常用的指令有哪些?vue 中如何自定义指令(全局和局部)?自定义指令接受哪些生命钩子函数?
26、如何声明一个过滤器(全局和局部)?你常用的自定义过滤器有哪些?
 
27、完整的 vue-router 导航解析流程
28、vue 路由的钩子函数
29、vue-router路由的两种模式?如何实现?有什么区别?如何定义 vue-router 的动态路由? 怎么获取传过来的值?
30、路由显示区域和路由跳转分别是哪个组件?$route 和 $router 有什么区别? 路由懒加载怎么实现,有什么意义?
31、vue-router的几种实例方法以及参数传递?
32、router的meta有什么用?怎样给路由添加 active-class?
33、vue2.x 的响应式原理?vue3.x响应式原理?
34、vuex 是什么?什么是“状态管理模式”?vuex 有哪些核心的属性?Vuex 和单纯的全局对象有什么区别?
35、vue中proxy代理?
36、vue中对象更改检测的注意事项
37、Vue.js 全局运行机制
38、vue 如何优化首屏加载速度?vue 弹窗后如何禁止滚动条滚动?
39、vue 开发命令 npm run dev 输入后的执行过程
40、devDependencies 和 dependencies 的区别
41、依赖版本 ~ 和 ^ 的区别
 
42、Vue项目性能优化
43、vue3.0 相对于 vue2.x 有哪些变化?
44、vue2.0 中如何检测数组变化?
45、插件
vue 如何兼容 IE
Vue项目中如何区分开发环境和生产环境

流程分析:

1、初始化以及挂载init, mount

2、在进行模板编译compile,将template编译为渲染函数render function

3、执行render function生成Virtual DOM, render function => VNode tree

4、再进行响应式依赖收集,render function => getter, setter => Watcher.update => patch。以及使用队列进行异步更新的策略。

 5、通过diff算法后进行patch更新视图

38、vue 如何优化首屏加载速度?vue 弹窗后如何禁止滚动条滚动?

vue优化首屏加载速度:

(1)按需加载组件,不一次性加载所有组件

(2)减少打包js,如果打包后的js文件过大,会阻塞加载。

(3)关闭sourcemap,开启压缩代码 vue.config.js文件中配置:productionSourceMap: false,

(4)加个好看的loading效果

vue弹窗后禁止滚动条滚动:

methods : {
    //禁止滚动
    stop(){
        var mo=function(e){e.preventDefault();};
        document.body.style.overflow='hidden';
        document.addEventListener("touchmove",mo,false);//禁止页面滑动
},
    /***取消滑动限制***/
    move(){
        var mo=function(e){e.preventDefault();};
        document.body.style.overflow='';//出现滚动条
        document.removeEventListener("touchmove",mo,false);
}

39、vue 开发命令 npm run dev 输入后的执行过程

(1)npm run dev是执行配置在package.json中的脚本

(2)调用了webpack配置文件

(3)配置文件中调用了main.js

(4)main.js用到了一个html元素#app,引用路由等开始vue的模板编译

40、devDependencies 和 dependencies 的区别

(1)devDependencies:用于本地开发,打包时生产环境不会打包这些依赖。

(2)dependencies:开发环境能用,生产环境也能用。生产环境会被打包。

41、依赖版本 ~ 和 ^ 的区别

(1)~:会匹配最近的小版本依赖包,比如~1.2.3会匹配所有1.2.x版本,但是不包括1.3.0

(2)^:会匹配最新的大版本依赖包,比如^1.2.3会匹配所有1.x.x的包,包括1.3.0,但是不包括2.0.0

 

42、Vue项目性能优化

编码阶段:

代码减少对服务器请求次数,减小对服务器请求代码的体积

尽量减少data中的数据,data中的数据都会增加 getter 和 setter,会收集对应的 watcher

 v-if 和v-for 不能连用、在更多的情况下,使用v-if替代 v-show

 如果需要使用 v-for 给每项元素绑定事件时使用事件代理,key保证唯一

 SPA页面采用 keep-alive 缓存组件

使用路由懒加载、异步组件、图片懒加载、css精灵图字体图标

 防抖、节流、第三方模块按需导入、长列表滚动到可视区域动态加载、全局事件解绑

SEO优化: 预渲染、服务端染SSR

打包优化: 压缩代码、使用cdn加载第三方模块、多线程打包 happypack、splitChunks抽离公共文件、sourceMap优化、Tree Shaking/Scope Hoisting

用户体验: 骨架屏、PWA、使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩

 webpack

封装axios 请求超时时间, baseurl设置, 请求头设置 (token 的设置) 错误的处理 (未登录) token过期 404 (算也不算优化,这都是正常开发的功能,如果说这样可以优化结构复用也合理)

参考这篇文章: https://www.cnblogs.com/chaoyuehedy/p/9931146.html

43、vue3.0 相对于 vue2.x 有哪些变化?

监测机制的改变( Object.defineProperty-> Proxy)、模板、对象式的组件声明方式(class)、使用 ts

其它方面的更改:支持自定义渲染器、支持 Fragment(多个根节点)和 Protal(在dom其他部分渲染组建内容)组件、基于 treeshaking优化,提供了更多的内置功能

44、vue2.0 中如何检测数组变化?

Vue的 Observer对数组做了单独的处理,对数组的方法进行编译,并赋值给数组属性的 proto 属性上,因为原型链的机制,找到对应的方法就不会继续往上找了。编译方法中会对一些会增加索引的方法(push, unshift, splice)进行手动 observe。

45、插件

插件:插件通常用来为 Vue 添加全局功能。插件的功能范围没有严格的限制;(插件按照vue格式编写的js代码,可以通过use注册,然后使用)

一般有下面几种:

 添加全局方法或者 property。如:vue-custom-element

添加全局资源:指令/过滤器/过渡等。如 vue-touch

通过全局混入来添加一些组件选项。如 vue-router

 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。

一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router

怎么注册插件: (看原稿)

 使用全局方法Vue.use()

Vue.use( MyPlugin )

com.js中
import com from './xx.vue'
  let test = {}
  test.install = function(Vue,options){
  Vue.component(panel.name, panel)  // 注册全局组件
}
export default com

main.js中
import com from './com.js'
Vue.use(com)

所有vue文件中都可以调用组件<com></com>

vue 如何兼容 IE

vue本身不支持旧版本 ie ,而旧版 js 也不支持属性监听,所以 vue 不支持兼容 ie。

如果要兼容低版本,建议使用 jquery 系列技术

react 如何兼容 ie ?加上polyfill可以兼容IE8。

Vue项目中如何区分开发环境和生产环境

用webpack定义两个配置文件,分别代表开发环境和生产环境即可

区分环境的问题,就是写两个配置文件运行的时候,用不同的文件就行了

如何让 css 只在当前组件起作用? 在style标签中写入scoped即可

vue.js 的两个核心是什么? 数据驱动、组件系统

$set 方法有什么用?有什么特点?添加响应式的属性

暂时到这里,后续有的话在再继续补进去!有问题的话麻烦指出来,好让我修改!