总结最近我和几个同事遇到的面试题,希望对大家有帮助,面试题我分为两类,经常遇到,很少遇到

目录

经常遇到

1、vue的生命周期

2、computed和watch区别?

3、深度监听怎么做

4、父子组件的生命周期的顺序

5、setTimeout是在生命周期的什么阶段销毁的?如果不销毁会怎么样?

6、父子组件通信用什么? 兄弟组件通信呢?

7、路由守卫

9、vue的修饰符有哪些?

10、vuex中mulation和actions的区别和联系

11、MVC与MVVM的区别?目前有哪些是用到是MVC,哪些用的是MVVM?

12、npm的package.json中,版本号前面的^和~

13、this.$nextTick原理和使用场景

14、Vue v-for不设置index索引为key值的原因?v-for为什么一定要设置key?

15、Eventloop事件循环机制

16、为什么避免 v-if 和 v-for 一起用?

17、Mixins的优缺点

18、Vue的axios

19、vue-router的两种模式

20、说出至少4种vue指令和它的用法?

21、 Vue如何创建自定义指令?

22、vue-loader是什么?用途有哪些?

23、scss 是什么?在 vue.cli 中的安装使用步骤?有哪几大特性?

24、动态绑定 Class 有几种方式?

25、如何定义 vue-router 动态路由以及如何获取传过来的动态参数?

很少遇到:

1、VNode 是什么?虚拟 DOM 是什么?

2、使用虚拟DOM的好处

3、动态组件的使用场景

4、vue中有处理过内存泄露问题吗

5、watch的各个属性

6、transion动画具体实现

7、路由守卫的next(),路由守卫使用场景

8、React和vue区别

9、vue与react虚拟dom的区别

10.实现观察者模式

11、父组件如何监听子组件的生命周期?

经常遇到

1、vue的生命周期

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

创建前/后: 在beforeCreate阶段,由于还未初始化,vue实例的挂载元素el和数据对象data都为undefined。在created阶段,vue实例的数据对象data有了,el还没有。

载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但挂载之前还是为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。

更新前/后:当data变化时,会触发beforeUpdate和updated方法。

销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在。

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

 若引入keep-alive,就多了activated,deactivated这两个生命周期函数

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

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

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

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

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

第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子

(5)DOM 渲染在 哪个周期中就已经完成?

DOM 渲染在 mounted 中就已经完成了。

(6)简单描述每个周期具体适合哪些场景?

生命周期钩子的一些使用方法:

beforecreate : 可以在此阶段加loading事件,在加载实例时触发;

created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用;

mounted : 挂载元素,获取到DOM节点;

updated : 如果对数据统一处理,在这里写上相应函数;

beforeDestroy : 离开的时候,需要销毁的数据,或者需要停止的事件

nextTick : 更新数据后立即操作dom;
 

2、computed和watch区别?

watch和computed都是以Vue的依赖追踪机制为基础的,它们都试图处理这样一件事情:当某一个数据(称它为依赖数据)发生变化的时候,所有依赖这个数据的“相关”数据“自动”发生变化,也就是自动调用相关的函数去实现数据的变动。

computed:计算属性是依赖的值改变会重新执行函数,计算属性是取返回值作为最新结果,所以里面不能异步的返回结果。不能写异步逻辑。计算属性基于响应式依赖进行缓存。如其中的任意一个值未发生变化,它调用的就是上一次计算缓存的数据,因此提高了程序的性能。

watch:computed和watch都是依赖数据发生变化后而执行的操作,但是计算属性初始化的时候就可以被监听到并且计算, 但是watch是发生改变的时候才会触发。当你有一些数据需要随着其它数据变动而变动时,或者当需要在数据变化时执行异步或开销较大的操作时,你可以使用 watch。
侦听属性是侦听的值改变会重新执行函数,将一个值重新赋值作为最新结果,所以赋值的时候可以进行一些异步操作

watch和computed各自处理的数据关系场景不同

1.watch擅长处理的场景:一个数据影响多个数据

2.computed擅长处理的场景:一个数据受多个数据影响

3、深度监听怎么做

watch 里面还有一个属性 deep,默认值是 false,代表是否深度监听,设置为true时,可进行深度监听,任何属性发生变化,都可以监听到

deep的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了,任何修改obj里面任何一个属性都会触发这个监听器里的 handler。但是可以适当优化,我们可以对个别属性进行监听,使用字符串形式监听。
例如:

 watch: {
    'obj.a': {
      handler(newName, oldName) {
      // ...
      },
      deep: true,
      immediate: true
    }
  }

immediate:true (立即执行)这个配置也要慎用

4、父子组件的生命周期的顺序

挂载阶段

该过程主要涉及 beforeCreate、created、beforeMount、mounted 4 个钩子函数。执行顺序为:
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted

父beforeMount要先完成虚拟dom的编译工作,父没完成,怎么可能会有子呢,所以 父beforeMount -> 子beforeCreate
一定得等子组件挂载完毕后,父组件才能挂在完毕,所以父组件的 mounted 在最后。

子组件更新阶段
该过程主要涉及 beforeUpdate、updated 2 个钩子函数。注意,当父子组件有数据传递时,才有这个更新阶段执行顺序的比较。执行顺序为:
父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated

父组件更新过程

父beforeUpdate ->父updated

销毁阶段
该过程主要涉及beforeDestroy、destroyed 2 个钩子函数。执行顺序为:
父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed

总结
Vue 父子组件生命周期钩子的执行顺序遵循:从外到内,再从内到外。
 

5、setTimeout是在生命周期的什么阶段销毁的?如果不销毁会怎么样?

setTimeout是beforeDestroy 销毁的,

不销毁内存、占用空间、最终导致浏览器崩溃

6、父子组件通信用什么? 兄弟组件通信呢?

父子组件通信:

prop:父传子,子通过prop接收

$emit: 父组件上封装了一个on的事件用来监听子组件的事件

兄弟组件通过evenBus,evenBus就是定义了一个new vue(),这个实例相当于封装了一个发布者-订阅者模式,

可参考Vue.js 父子组件通信的十种方式_Joy__Yue的博客-CSDN博客_vue 父子组件通信

7、路由守卫

导航守卫就是路由跳转前、中、后过程中的一些钩子函数,这个函数能让你操作一些其他的事儿,这就是导航守卫。

导航守卫分为:全局的组件内的单个路由独享三种

全局的:

  • beforeEach
    在路由跳转前触发,参数包括to,from,next(参数会单独介绍)三个,这个钩子作用主要是用于登录验证
  • beforeResolve(2.5+)
    这个钩子和beforeEach类似,也是路由跳转前触发,参数也是to,from,next三个,与beforeEach的区别参考官网。
  • afterEach
  • 是在路由跳转完成后触发,参数包括to,from,它发生在beforeEach和beforeResolve之后,beforeRouteEnter(组件内守卫)之前。

组件内的:

 beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }

单个路由独享:

指在单个路由配置的时候也可以设置的钩子函数

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

路由独享的钩子函数包括

  • beforeEnter
    与全局的beforeEach完全相同,如果都设置则在beforeEach之后紧随执行,参数to、from、next

8、如何实现双向数据绑定?

vue使用Object.defineProperty来劫持对象属性的getter和setter方法,属性值在编译时,会创建相应的订阅者Watcher,和依赖收集器dep,当属性值发生改变的时候,会触发set方法,set方法调用dep依赖收集器,通知订阅者Watcher,订阅者触发更新函数更新视图。(数据更新驱动视图更新)

当编译模板的过程中,对文本输入元素添加原生dom监听事件,监听视图文本变化,然后通知数据更新。(视图更新推动数据更新)

9、vue的修饰符有哪些?

一、事件修饰符
.stop 阻止事件继续传播
.prevent 阻止标签默认行为
.capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理
.self 只当在 event.target 是当前元素自身时触发处理函数
.once 事件将只会触发一次
.passive 告诉浏览器你不想阻止事件的默认行为

<a v-on:click.stop="doThis"></a>

二、 v-model的修饰符
<1> .lazy    默认情况下,v-model同步输入框的值和数据。可以通过这个修饰符,转变为在change事件再同步。
<2> .number   自动将用户的输入值转化为数值类型
<3> .trim     自动过滤用户输入的首尾空格

<input v-model.trim="msg">

三、键盘事件的修饰符

.enter 回车键
.tab 制表键
.esc 返回键
.space 空格键
.up 向上键
.down 向下键
.left 向左建
 .right 向右键

例如:

<input @keyup.enter="submit">  

修饰键:(也叫系统修饰符)

.ctrl
.alt
.shift
.meta (就是ctrl旁边的window图标键)

例如:

<!-- 按下Ctrl + enter时触发 -->
<input @keydown.ctrl.13="submit">

v-bind修饰符

.sync

.sync修饰符,它只是作为一个编译时的语法糖存在。它会被扩展为一个自动更新父组件属性的 v-on 监听器 

<comp :foo.sync="bar"></comp>

扩展为:

<comp :foo="bar" @update:foo="val => bar = val"></comp>


当子组件需要更新foo的值时,它需要显式的触发更新事件,如下:

this.emit('update:foo', newValue)

也可参考vue中sync修饰符_汉三姓胡的博客-CSDN博客_vuesync修饰符

除了上述以外还有一个.native,加上.native之后,原生事件不生效,一般用于封装的组件。

也可参考:

vue中的修饰符_star@星空的博客-CSDN博客

10、vuex中mulation和actions的区别和联系

actions

1、用于通过提交mutation改变数据

2、会默认将自身封装为一个Promise

3、可以包含任意的异步操作

mutation

1、通过提交commit改变数据

2、只是一个单纯的函数

3、不要使用异步操作,异步操作会导致变量不能追踪

11、MVC与MVVM的区别?目前有哪些是用到是MVC,哪些用的是MVVM?

MVVM是model-view-viewModel的缩写,mvvm是一种设置模式,model代表的是数据模型,也可以在Model中定义数据修改和操作的业务逻辑;View 代表UI 组件,它负责将数据模型转化成UI 展现出来,ViewModel 是一个同步View 和 Model的对象。

在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。

ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

MVC和MVVM其实区别并不大,都是一种设计思想。主要就是mvcController演变成mvvm中的viewModelmvvm主要解决了mvc中大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。

目前三大框架vue、react、angular基本都是mvvm模式了,之前老的项目可能会用到mvc,例如angular.js,不过现在用angular.js开发的基本很少了。

12、npm的package.json中,版本号前面的^和~

波浪号〜匹配最新补丁版本号,也就是版本号的第三个数字。比如~1.2.3将匹配所有1.2.x版本,但将在1.3.0上停止。

插入符号^ 更宽松。 它匹配的是最新次要版本号,也就是第二个数字。比如:^ 1.2.3将匹配任何1.x.x版本,包括1.3.0,但将在2.0.0上停止。

星号*匹配任意版本,一般不用

latest意思安装的永远是最新的版本

还可以1.2.x形式匹配1.2z之后的任意版本1.2.1  1.2.2,不能是1.3.0

13、this.$nextTick原理和使用场景

原理:
this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。假设我们更改了某个dom元素内部的文本,而这时候我们想直接打印出这个被改变后的文本时,需要dom更新之后才能获取到更新后的值,也就好比我们将打印输出的代码放setTimeout(fn, 0)中;
应用场景:需要在视图更新之后,基于新的视图进行操作。
this.$nextTick()方法主要是用在数据改变,dom改变应用场景中。vue中数据和dom渲染由于是异步的,所以,要让dom结构随数据改变这样的操作都应该放进this.$nextTick()的回调函数中。created()中使用的方法时,dom还没有渲染,如果此时在该钩子函数中进行dom赋值数据(或者其它dom操作)时无异于徒劳,所以,此时this.$nextTick()就会被大量使用,而与created()对应的是mounted()的钩子函数,则是在dom完全渲染后才开始渲染数据,所以在mounted()中操作dom基本不会存在渲染问题。

详情可参考this.$nextTick()的使用场景_马优晨的博客-CSDN博客_$nexttick的使用场景

14、Vue v-for不设置index索引为key值的原因?v-for为什么一定要设置key?

Key是dom用来做 diff算法比较用的,比较当前标签上的key还有它当前的标签名,如果key和标签名都一样时只是做了一个移动的操作,不会重新创建元素和删除元素,但index不是对象的唯一标识,例如删除数组的时候,部分数据的index都要发生变化,要重新渲染一次,影响了性能,有时还会产生bug,不涉及节点增删时,可以使用索引充当key值,不过最好使用数组中的对象中的唯一键作为key.即[{id:xx,...},{id:xxx,...}]中的id作为key.这可避免节点增删时出现数据或其他错误,

再比如当向数组中指定位置插入一个新元素后,因为这时候会重新更新index索引,对应着后面的虚拟DOM的key值全部更新了,这个时候还是会做不必要的更新,就像没有加key一样,因此index虽然能够解决key不冲突的问题,但是并不能解决复用的情况。如果是静态数据,用索引号index做key值是没有问题的。标签名一样,key一样这时候就会就地复用,如果标签名不一样,key一样不会复用。

  v-for为什么一定要设置key?

 首先在开发中我们会发现v-for遍历的时候,如果v-for遍历不设置key值,eslint检查会报错,

其次没有key的时候默认使用的是“就地复用”策略。如果数据项的顺序被改变,Vue不是移动Dom元素来匹配数据项的改变,而是简单复用原来位置的每个元素。如果删除第一个元素,在进行比较时发现标签一样值不一样时,就会复用之前的位置,将新值直接放到该位置,以此类推,最后多出一个就会把最后一个删除掉。这样频繁操作dom,消耗内存。

总结在无key的情况下,我们做数组删除时,可能修改了多次dom,但在有key的情况下,只需移动删除,不需要去修改dom,所以我们在使用v-for写上key,可防止一会修改数据的时候,出现bug。

具体可参考vue核心面试题:v-for中为什么要用key_王三六的博客-CSDN博客_为什么使用key

15、Eventloop事件循环机制

  首先。将"执行栈"最开始的同步代码(宏任务)执行完成;

(2)检查是否有微任务。如有则执行所有的微任务;

(3)取出"任务队列"中事件所对应的回调函数(宏任务)进入”执行栈“并执行完成;

(4)再检查是否有微任务,如有则执行所有的微任务;

(5)主线程不断重复上面的(3)(4)步骤;

宏任务:同步代码,setTimeout,setInterval,requestAnimationFrame,I/O,UI rendering

微任务:process.nextTick,

promise callback,MutationObserver

16、为什么避免 v-if 和 v-for 一起用?

当 Vue 处理指令时,v-for 比 v-if 具有更高的优先级,通过v-if 移动到容器元素,不会再重复遍历列表中的每个值。取而代之的是,只检查它一次,且不会在 v-if 为否的时候运算 v-for

17、Mixins的优缺点

混入的优点:可以将一些组件通用的属性,方法,生命周期事件抽离出来,通过混入的方式来使用,使代码复用性更高;
缺点:容易被滥用

18、Vue的axios

axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:

1、从浏览器中创建 XMLHttpRequest

2、从 node.js 发出 http 请求

3、支持 Promise API

4、拦截请求和响应

5、转换请求和响应数据

6、取消请求

7、自动转换JSON数据

8、客户端支持防止 CSRF/XSRF

具体使用可参考关于VUE的vue-axios使用_kikpin的博客-CSDN博客_vueaxios

19、vue-router的两种模式

hash模式和history模式

hash模式:

  • 使用URL的hash来模拟一个完整的URL,于是当URL改变的时候,页面不会重新加载,也就是单页应用
  • 当#后面的hash发生变化时,不会导致浏览器向服务器发出请求,浏览器不发出请求就不会刷新页面,并且会触发hasChange这个事件,通过监听hash值的变化来实现更新页面部分内容的操作

history模式:主要使用HTML5的pushState()和replaceState()这两个api来实现的

  • pushState()可以改变url地址且不会发送请求
  • replaceState()可以读取历史记录栈,还可以对浏览器记录进行修改

区别:前面的hashchange,你只能改变#后面的url片段。而pushState设置的新URL可以是与当前URL同源的任意URL。
history模式则会将URL修改得就和正常请求后端的URL一样,如后端没有配置对应/user/id的路由处理,则会返回404错误

vue-router的两种模式的区别_大尾巴XYW的博客-CSDN博客_vue-router的两种模式

20、说出至少4种vue指令和它的用法?

 v-if:判断是否隐藏;

 v-for:数据循环;

 v-bind:class:绑定一个属性;

v-model:实现双向绑定;

21、 Vue如何创建自定义指令?

vue指令也分全局自定义指令局部自定义指令

全局的直接Vue.directive('指令名',方法) 方法包括:

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置

inserted:被绑定元素插入父节点时调用   (仅保证父节点存在,但不一定已被插入文档中)

update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新

componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用

unbind:只调用一次,指令与元素解绑时调用

自定义指令 — Vue.js


22、vue-loader是什么?用途有哪些?

解析.vue文件的一个加载器。

用途:js可以写es6、style样式可以scss或less、template可以加jade等
 

23、scss 是什么?在 vue.cli 中的安装使用步骤?有哪几大特性?

css的预编译语言。

使用步骤:

第一步:先装css-loader、node-loader、sass-loader等加载器模块;

第二步:在build目录找到webpack.base.config.js,在extends属性中加一个拓展.scss;

第三步:在同一个文件,配置一个module属性;

第四步:然后在组件的style标签加上lang属性 ,例如:lang=”scss”;

特性:

  • 可以用变量,例如($变量名称=值);
  • 可以用混合器;
  • 可以嵌套;

Vue进阶(幺柒陆):CSS 预编译语言 Sass、Scss、Less 和 Stylus_No Silver Bullet的博客-CSDN博客

Vue进阶(幺柒柒):Vue 应用 Sass、Scss、Less 和 Stylus_No Silver Bullet的博客-CSDN博客


24、动态绑定 Class 有几种方式?

  • 凡是有-的style属性名都要变成驼峰式,比如font-size要变成fontSize;
  • 除了绑定值,其他的属性值要用引号括起来,比如backgroundColor:'#00a2ff'而不是 backgroundColor:#00a2ff;

对象

html :style="{ color: activeColor, fontSize: fontSize + 'px' }"

html :style="{color:(index==0?conFontColor:'#000')}"

 数组

html :style="[baseStyles, overridingStyles]"
html :style="[{color:(index==0?conFontColor:'#000')},{fontSize:'20px'}]

三目运算符

html :style="{color:(index==0?conFontColor:'#000')}"
html :style="[{color:(index==0?conFontColor:'#000')},{fontSize:'20px'}]"

多重值
此时,浏览器会根据运行支持情况进行选择

html :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"

 绑定data对象

html :style="styleObject"
data() {
    return{
      styleObject: {
        color: 'red',
        fontSize: '13px'
      }  
    }
}

25、如何定义 vue-router 动态路由以及如何获取传过来的动态参数?

动态路由:动态配置路由参数,页面刷新,数据不丢失

this.$router.push({
       path: `/particulars/${id}`,
     })

接收页面通过 this.$route.params.id 接收

获取路由传过来的参数

两种实现方式:

路由 name 匹配,通过 params 传参

 this.$router.push({
        name: 'particulars',
        params: {
          id: id
        }
      })

路由配置

 {
   path: '/particulars',
   name: 'particulars',
   component: particulars
 }

也是通过 this.$route.params.id 接收参数

路由 path 路径匹配,通过 query 传参

通过query来传递参数,这种情况下 query传递的参数会显示在url后面以?id=?形式展示。

    this.$router.push({
      path: '/particulars',
      query: {
        id: id
      }
   })

路由配置

{
  path: '/particulars',
  name: 'particulars',
  component: particulars
}

通过 this.$route.query.id 接收参数
区别

  1. query要用path来引入,params要用name来引入,接收参数都是类似的,分别是this.$route.query.namethis.$route.params.name
  2. query更加类似于ajaxget传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示。

很少遇到:

1、VNode 是什么?虚拟 DOM 是什么?

Vue在页面上渲染的节点,及其子节点称为“虚拟节点 (Virtual Node)”,简写为“VNode”。“虚拟 DOM”是由 Vue 组件树建立起来的整个 VNode 树的称呼。

2、使用虚拟DOM的好处

web界面由DOM树来构建,当其中一部分发生变化时,其实就是对应某个节点发生了变化。
虚拟DOM就是为了解决浏览器性能问题而被设计出来的。若一次操作DOM中有十次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这十次更新的diff内容保存到本地一个js中,最终将这个js对象一次性attach 到DOM树上,在进行后续操作。避免大量无谓的计算量。所以,用js对象模拟DOM节点的好处是,页面的更新可以先全部反应在js对象(虚拟DOM)上,操作内存中的js对象的速度显然要更快,等更新完成之后,再将最终的js对象映射成真实的DOM,交由浏览器去绘制。因此使用虚拟 DOM 速度快,减小了页面渲染过程的次数。

3、动态组件的使用场景

可以让组件根据需求动态显示,一般用于需要根据数据动态渲染的场景或类似tab切换栏,即组件类型不确定。使用起来也特别简单,一般用于tab系列的组件。

4、vue中有处理过内存泄露问题吗

1>意外的全局变量
函数中意外的定义了全局变量,每次执行该函数都会生成该变量,且不会随着函数执行结束而释放。

2>未清除的定时器
定时器没有清除,它内部引用的变量,不会被释放。

3>脱离DOM的元素引用
一个dom容器删除之后,变量未置为null,则其内部的dom元素则不会释放。

4>持续绑定的事件
函数中addEventListener绑定事件,函数多次执行,绑定便会产生多次,产生内存泄漏。

5>绑在EventBus的事件没有解绑

6>闭包引起内存泄漏
比如事件处理回调,导致DOM对象和脚本中对象双向引用。

7>使用第三方库创建,没有调用正确的销毁函数

8>单页应用时,页面路由切换后,内存未释放

可参考Vue系列之常见内存泄漏定位与解决_好未来技术团队的博客-CSDN博客_vue 内存泄漏

5、watch的各个属性

vm.$watch( expOrFn, callback, [options] )

  • 参数

    • {string | Function} expOrFn
    • {Function | Object} callback
    • {Object} [options]
      • {boolean} deep
      • {boolean} immediate

watch中可以执行任何逻辑,如函数节流,Ajax异步获取数据,甚至操作 DOM(不建议)。既可以对data中的属性进行监听,也可以对某个对象的属性值进行监听

   a: function(val, oldVal) {
     ...
   },
   "b.c": function(val, oldVal) {
     ...
   },

 也可以进行深度监听

    obj: {
      handler: function(newVal, oldVal) {
            console.log(newVal); 
       },
       deep: true,
       immediate: true 
     }

handler: 监听的回调

deep:

 默认值是fasle,是否要进行深度监听,注意监听数组的变更不需要这么做。

immediate:

在选项参数中指定 immediate: true 将立即以表达式的当前值触发回调,慎用,可以看上面的第三题

6、transion动画具体实现

  1. Vue中的过度动画(无name属性的transition)
  2. Vue中的过度动画(有name属性的transition)
  3. Vue中的关键帧动画 
  4. vue中的js动画

可参考Vue中使用 transition标签实现动画的 4种方法 (八)_机智的前端小白的博客-CSDN博客_vue的transition过渡动画

7、路由守卫的next(),路由守卫使用场景

next() 是放行,但是如果next()里有参数的话,next()就像被重载一样,就有了不同的功能。

其他的诸如:next('/logon') 、 next(to) 或者 next({ ...to, replace: true })都不是放行,而是:中断当前导航,执行新的导航

使用场景:跳转时,登陆失效,或已登陆状态又去跳转登陆



VUE 路由守卫 next() / next({ ...to, replace: true }) / next(‘/‘) 说明_Incimo的博客-CSDN博客_next({...to, replace: true})

8、React和vue区别

 1、监听数据变化的实现原理不同

 2、数据流的不同react没有双向数据绑定,是单向数据流,react中通过将state(Model层)与View层数据进行双向绑定达数据的实时更新变化,具体来说就是在View层直接写JS代码Model层中的数据拿过来渲染,一旦像表单操作、触发事件、ajax请求等触发数据变化,则进行双同步

 3、HoC和mixins

    Vue组合不同功能的方式是通过mixin,React组合不同功能的方式是通过HoC(高阶组件)

4、组件通信的区别;而Vue中子组件向父组件传递消息有两种方式:事件和回调函数,但Vue更倾向于使用事件。在React中不支持自定义事件,我们都是使用回调函数的,这可能是他们二者最大的区别

5、模板渲染方式的不同

在表层上,模板的语法不同,React是通过JSX渲染模板。而Vue是通过一种拓展的HTML语法进行渲染,但其实这只是表面现象,毕竟React并不必须依赖JSX。

6、渲染过程不同
Vue可以更快地计算出Virtual DOM的差异,这是由于它在渲染过程中,会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。

React在应用的状态被改变时,全部子组件都会重新渲染。通过shouldComponentUpdate这个生命周期方法可以进行控制,但Vue将此视为默认的优化。

如果应用中交互复杂,需要处理大量的UI变化,那么使用Virtual DOM是一个好主意。如果更新元素并不频繁,那么Virtual DOM并不一定适用,性能很可能还不如直接操控DOM。

7.框架本质不同
Vue本质是MVVM框架,由MVC发展而来;React是前端组件化框架,由后端组件化发展而来。

8.Vuex和Redux的区别

Redux使用的是不可变数据,而Vuex的数据是可变的,因此,Redux每次都是用新state替换旧state,而Vuex是直接修改。Redux在检测数据变化的时候,是通过diff的方式比较差异的,而Vuex其实和Vue的原理一样,是通过getter/setter来比较的,这两点的区别,也是因为React和Vue的设计理念不同。React更偏向于构建稳定大型的应用,非常的科班化。相比之下,Vue更偏向于简单迅速的解决问题,更灵活,不那么严格遵循条条框框。因此也会给人一种大型项目用React,小型项目用Vue的感觉。

Vue.js与React的全面对比_ArmorVon的博客-CSDN博客_vue和react区别

9、vue与react虚拟dom的区别

dom的更新策略不同
react 会自顶向下全diff.
vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。
1. 在react中,当状态发生改变时,组件树就会自顶向下的全diff, 重新render页面, 重新生成新的虚拟dom tree, 新旧dom tree进行比较, 进行patch打补丁方式,局部跟新dom. 所以react为了避免父组件跟新而引起不必要的子组件更新, 可以在shouldComponentUpdate做逻辑判断,减少没必要的render, 以及重新生成虚拟dom,做差量对比过程.
2. 在 vue中, 通过Object.defineProperty 把这些 data 属性全部转为 getter/setter。同时watcher实例对象会在组件渲染时,将属性记录为dep, 当dep 项中的 setter被调用时,通知watch重新计算,使得关联组件更新。Diff 算法借助元素的 Key 判断元素是新增、删除、修改,从而减少不必要的元素重渲染。
其实这个我也不是很清楚,react没开发过

10.实现观察者模式

vue中的双向数据绑定就是实现了观察者模式

11、父组件如何监听子组件的生命周期?

 初学者看到这个问题,以为是看错了,今天也是同事问我,以前面试很少问到这个问题,父组件监听子组件的生命周期通过两种方式:

方式1: $emit 

方法2:@hook

如何使用或者使用场景可参考

Vue中父组件如何能监听到子组件的生命周期_陌上花开然不归矣的博客-CSDN博客

Vue进阶(四十七):面试必备:2022 Vue经典面试题总结(含答案)_No Silver Bullet的博客-CSDN博客_vue面试题

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐