VUE常见面试题

692 阅读2分钟

1. 对于MVVM的理解

MVVM是model-view-viewModel的缩写

model代表的是数据模型,可以定义数据的修改和操作业务逻辑

view代表的是ui组件,可以将数据模型转化ui展现出来

viewModel可以操作数据模型,处理用户交互等。它是将model和view连接起来的一个对象,view和model本身是没有任何联系的。但model和viewmodel之间交互式双向的,所以view的改变会反应到model上,而model的改变也会反应到view上

2. vue的生命周期

定义:vue的生命周期指的是组件从创建到销毁的一系列过程。

beforeCreat(创建前) 数据观测还未开始 初始化还未开始

created(创建后) 已完成数据观测,初始化完成。但$el 属性还未显示出来

beforeMount(载入前) 相关的render函数首次被调用,实例已完成以下配置:编译模板,把data里面的数据和模板生成html。但此时还未挂载到页面上

mounted(载入后) 编译好的html替换el属性指向DOM对象,完成模板中的html渲染

beforeUpdate(更新前) 在数据更新前调用

updated(更新后) 在数据更新后调用

beforeDestroy(销毁前) 实例销毁前调用

destoryed(销毁后) 实例销毁后调用 所有实例销毁,所有事件监听器移除

3. vue的生命周期作用

vue生命周期中有许多事件钩子,可以利用这些事件钩子更好的操作业务逻辑

4. 第一次加载页面会触发哪些事件钩子

beforeCreate created beforeMount mounted

5. DOM渲染在哪个周期完成

mounted

6. vue实现双向数据绑定原理

vue数据的双向绑定是通过数据劫持结合发布者-订阅者模式来实现。通过Object.defineProperty重写data的get和set函数来实现

  • 实现过程

    • 首先对数据劫持我们需要设置一个监听器Obeserve来监听所有属性
    • 如果属性上发生变化了,就需要告诉订阅者watcher是否需要更新
    • 因为订阅者有很多个,所以需要一个消息订阅器(Dep)来专门收集这些订阅者,然后在监听器(Obeserve)和订阅者(watcher)之间进行统一管理
    • 我们还需要一个指令解析器(compile),对每个节点元素进行扫描和解析,将相关指令对应初始化成一个订阅者(watcher),并替换模板数据绑定相应的函数,此时当订阅者watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新试图

7. Object.defineProperty()

Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。有三个参数:

  • obj:要定义属性的对象
  • prop:要定义或修改的属性名称
  • descriptor:将被定义或修改的属性描述符
在对象中添加一个属性与数据描述符实例:
let o = {}
Object.defineProperty(o,'a'{
    vaule:37,
    writable:true,  //value能被赋值运算符改变
    configurable:true, //属性描述符能够改变,该属性能从对应的对象上删除
    enumerable:true  //属性能够出现在对象枚举属性中
})

在对象中添加一个属性与存取描述符实例:
var o;
Object.defineProperty(o,'b'{
    get:function(){
        return o;
    },
    set:function(newVal){
        o = newVal
    },
    configurable:true, //属性描述符能够改变,该属性能从对应的对象上删除
    enumerable:true  //属性能够出现在对象枚举属性中
})
o.b = 38

8. Object.defineProperty()来进行数据劫持有什么缺点

有一些对属性的操作,使用这种无法拦截。比如通过下标方式修改数组数据,vue内部通过重写函数解决了这个问题。在vue3.0中已经不使用这种方法了,而是通过proxy对对象进行代理,重而实现数据劫持。

9. 什么是Virtual DOM?为什么Virtual DOM比原生DOM快?

我对Virtual DOM的理解是:

  1. 首先对我们将要插入到文档中的DOM树进行结构分析,然后使用js对象将其表示出来
  2. 当页面的状态发生改变,对页面的DOM结构进行调整的时候,首先根据变更的状态,重新构建起一棵对象树
  3. 将这棵新的对象树和旧的对象树进行比较,记录下两棵树的差异。最后将记录有差异的地方应用到真正的DOM树中,这样视图就更新了。

我认为Virtual DOM这种方法对于我们需要大量操作DOM的时候,能够很好的提高操作效率。通过在操作前确定需要做最小的修改,所以比原生DOM快。

10. 如何比较两个DOM树的差异

两个树的完全diff算法的时间复杂度为0(n^3),但是在前端中,我们很少跨层级的移动元素,所以只需要比较同一层级的元素,这样就可以将算法的时间复杂度降低为0(n).

使用diff算法首先会对新旧两棵树进行一个深度优先遍历,这样每个节点都会有一个序号。在深度遍历的时候,每遍历到一个节点,就将这个节点和新的树中的节点进行比较。如果有差异,则将这个差异记录到一个对象中

在对列表元素进行对比的时候,由于TagName是重复的,所以不能使用这个来比较。我们需要给每个子节点加上一个key,列表对比的时候使用key来进行比较。这样我们才能复用老的DOM树的节点

11. vue组件参数传递方式

  • 父子组件间通信

    • 子组件通过props来接收父组件的数据。父组件在子组件上注册监听事件,子组件通过emit来触发事件向父组件发送数据
    • 通过ref给子组件设置一个名字。父组件通过this.$refs子组件名来获得子组件数据,子组件通过this.$parent来获得父组件数据
    • 通过provider/inject,在父组件中通过provider提供变量,子组件通过inject来将变量注入到组件中。无论子组件多深,子组件都能通过inject来获得父组件中provider中的数据
  • 兄弟组件间通信

    • 使用eventBus,创建一个事件中心,相当于中转站。用它来传递和接收事件
    • 通过$parent.$refs来获取到兄弟组件
  • 任意组件之间

    • 使用eventBus
    • vuex

12. vue的路由实现

hash模式和history模式

hash:在浏览器“#”符号 以及后面的字符都称之为hash。用window.location.hash读取。hash虽然在url中,但不被包括在http请求中。hash不会重载页面

history:。可以对浏览器历史记录栈进行修改以及监听到状态的改变

13. vue与react angular的区别

与angular的区别

相同:都支持指令、都支持过滤器、都支持双向数据绑定、都不支持低端浏览器

不同:angular学习成本更高,添加了更多特性。而vue提供的API比较直观简单。angular依赖对数据做脏检查,所以watcher越多越慢,而vue依赖追踪观察,且使用异步队列更新,所有数据都是独立触发

与react区别

相同:中心思想相同,一切都是组件,组件实例之间可以嵌套,都提供合理的钩子函数,都是以插件方式加载,在组件开发中都支持mixins特性

不同:react采用的virtual DOM会对渲染的结果做脏检查,vue在模板中提供了指令,过滤器等,可以非常方便快捷的操作virtual DOM

14. vue路由的钩子函数

beforeEach afterEach

beforeEach有三个参数,to代表的是要进入的路由对象,from代表的是要离开的路由对象。next是一个必须要执行的函数,如果不传参就执行下一个钩子函数,传入false就终止跳转,传入路径跳转到相应的路由。

15. vue-cli如何新增自定义指令

用directives创建局部指令、用Vue.directive创建全局指令

16. vue如何自定义一个过滤器

用fliter

17. 对keep-alive的理解

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

18. 让css只在当前起作用

在style标签加入scoped

19. $route$router的区别

$route是“路由信息对象”,包括path,params.query等路由信息参数。而$router是路由实例对象包括了路由的跳转方法、钩子函数等

20. vue.js的核心驱动是什么

数据驱动、组件系统

21. vue常用的几种指令

v-if v-else v-on v-for v-bind v-show

22. vue常用的修饰符

.prevent(提交事件不再重载页面) .stop(阻止事件冒泡) .caputre(事件侦听,事件发生时调用)

23. vue中key值作用

vue中key值作用可以分为两种情况

  1. v-if使用key值。由于vue会尽可能高效的渲染元素,通常会复用已有元素,而不是重新开始渲染。比如切换相同的input元素,前后用户输入的内容不会被清除掉,这是不符合需求的,因此可以通过key标识一个独立的元素,使用key的元素不会被复用
  2. v-for使用key值。用v-for更新渲染过的列表,它会默认使用就地复用的策略。如果数据的顺序发生改变,就会跟DOM元素的元素顺序不匹配。因此通过为每个列表项提供一个key值,便于vue跟踪元素身份,高效的更新渲染虚拟DOM

24. vue中mixin和mixins的区别

mixin用于全局混入,会影响到每个组件实例

mixins是如果多个组件有相同的业务逻辑,就可以将这些逻辑剥离出来,通过mixins混入代码。比如上拉下拉加载数据等逻辑。另外,mixins混入的钩子函数会先于组件的钩子函数执行,并且在遇到同名选项时也会选择性的进行合并。

25. computed和wacth的区别

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

computed

  • 是计算值
  • computed擅长处理场景是:一个数据受多个数据影响(多对一)
  • 支持缓存,只有依赖数据发生变化,才会重新计算
  • 不支持异步。当里面有异步操作时,无法监听数据的变化

watch

  • 是观察动作
  • wacth擅长的处理场景是:一个数据影响多个数据(一对多)
  • 不支持缓存,数据改变会直接触发相应操作
  • wacth支持异步

26. vue等单页面应用及其优缺点

优点:

  • 用户体验好,快,内容的改变不需要重新加载整个页面,对服务器压力较小
  • 前后端分离
  • 完全前端组件化,前端开发不再以页面为单位,更多采用组件化思想,代码结构和组织方式更加规范化,便于修改维护

缺点:

  • 首次加载页面耗时较长
  • 不利于SEO,单页页面,数据在前端渲染,就意味着没有SEO
  • 页面导航不可用
  • 不支持低版本浏览器

27. slot插槽

1. 单个插槽

当子组件只有一个没有属性的插槽时,父组件传入整个内容片段插入到插槽的所在位置,并替换插槽本身

2. 具名插槽

slot有一个name属性来配置如何分发内容,将父组件模板中slot位置,和子组件slot元素产生关联。便于插槽内容对应传递

3. 作用域插槽

可以访问组件内部数据的可复用插槽。在父组件中的template上使用slot-scope属性。

28. v-show和v-if的区别

v-show控制元素的隐藏和显示,是css切换 v-if是销毁元素和创建元素

29. 绑定class的方法

1. 对象方法
:class="{'active': isActive, 'red': isRed}"
2. 数组方法
:class="[class1,class2]"
3. 行内
:style="{color:color. fontSize:fontSize+'px'}"

30. vuex是什么

一个专为vue.js开发的状态管理模式,它采用集中存储管理应用的所有组件状态,并以相应的规则保证状态以一种可预测的方式发生改变

它有五大核心属性 state、getter、mutation、action、module

state:存储数据,存储状态。用this.$store.state访问

getter:可以认为是store的计算属性。它的返回值会根据它的依赖被缓存起来。

mutation: 更改store中的状态的唯一方法是提交mutation

action: 提交mutation,可以包含任何异步操作

module: 将store分割成各个模块

31. v-model的原理

比如一个输入框v-model了一个message。p标签绑定了这个message,当输入框的数据改变,p标签文本也会改变。其实就是帮忙监听了input事件。并把这个input事件所携带的值传给v-model属性。这样组件内部的值就给到了父组件

其他相关面试题