vue面试题大全持续更新中……

101 阅读7分钟

1、vue的介绍

  • vue是一套用于构建用户界面的渐进式框架
  • vue尤雨溪开发的
  • vue的特点
    • 采用组件化模式,提高代码复用率,且让代码更好维护
    • 声明式编码,让编码人员无需直接操作DOM,提高开发效率
    • 使用虚拟DOM+优秀的diff算法,尽量复用DOM节点

2、vue的生命周期

vue实例从创建到销毁的过程中会伴随一些函数的自调用,我们通常称这些函数为钩子函数。

生命周期
beforeCreate在实例初始化之后,数据观测和时间配置之前被调用此时data和methods以及页面的DOM结构都没有初始化什么都做不了
created在实例创建完成后被立即调用此时data和methods已经可以使用但是页面还没有渲染出来
beforeMount在挂载(el)开始之前被调用此时页面上还看不到真是数据只是一个模板页面而已
mountedel被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。数据已经真实渲染到页面上在这个钩子函数里面我们可以使用一些第三方的插件
beforeUpdate数据更新时调用,发生在虚拟DOM打补丁之前,页面上数据还是旧的
updated由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。页面上数据已经替换成最新的
beforeDestory实例销毁之前调用
destoryed实例销毁后调用

3、vue:v-model的原理

v-model的实现原理大致是,通过Object.defineProperty()方法来劫持Vue数据的属性,一旦监听到数据的变化,则更新数据管理的虚拟DOM树,当然在模板编译的时候,为指令v-model绑定input事件,当输入的内容发生改变时,同步更新data中绑定的数据

4、vue中操作data中数组的方法中哪些可以触发视图更新,那些不可以,不可以的话有什么解决办法?

  • 可以被改变的
    • push()、pop()、shift()、unshift()、splice()、sort()、reserve()这些方法会改变操作的数组
  • 不可以改变的
    • filter()、concat()、slice()这些方法不会改变被操作的数组,并且返回一个新的数组,以上方法都可以触发视图更新
  • 解决方案
    • 利用索引直接设置以恶搞数组项,直接修改数组的长度
  • 以上两种方法不可以触发视图更新
    • 可以使用this.$set(this.array,index,newValue),this.array.splice(index,1,newValue)
    • 可以使用this.array.solice(newLength)

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

  • Vnode是什么
    • vnode是JavaScript对象,Vnode表示Virtual DOM,用JavaScript对象来描述真实的DOM把DOM标签,属性,内容都变成对象的属性。就像使用JavaScript对象对一种动物进行说明一样{name:"hello kitty",age:1,children:null}
  • Vnode的作用
    • 通过render将template模板描述成Vnode,然后进行一系列操作之后形成真实的DOM进行挂载
  • Vnode的优点
    • 兼容性强,不受执行环境的影响,Vnode因为是JS对象,不管node还是浏览器,都可以统一操作,从而获得了服务端渲染、原生渲染、手写渲染函数等能力。
    • 减少操作DOM,任何页面的变化,都只使用Vnode进行操作对比,只需要在最后一步挂载更新DOM,不需要频繁操作DOM,从而提高页面性能。
  • 什么是虚拟DOM
    • 文档对象模型或DOM定义了一个接口,该接口允许JavaScript之类的语言访问和操作HTM文档。元素由树中的节点表示,并且接口允许我们操纵他们,但是此接口需要付出代价,大量非常频繁的DOM操作会使页面速度变得非常缓慢
    • Vue通过在内存中实现文档结构的虚拟表示来解决此问题,其中虚拟节点(Vnode)表示DOM树中的节点。当需要操纵时,可以在虚拟DOM的内存中执行计算和操作,而不是在真实DOM上进行操纵,这自然会更快,并且允许虚拟DOM算法计算出最优化的方式来更新实际DOM结构,一旦计算出,就将其应用于实际的DOM树,这就提高了性能,这就是为什么基于虚拟DOM的框架如此突出的原因

6、vue中如何实现一个虚拟DOM?说说你的思路

首先要创建一个Vnode的类,DOM元素上的所有属性在Vnode类实例化出来的对象上都存在对应的属性,例如tag表示以恶搞元素节点的名称,text表示一个文本节点的文本,children表示子节点等。将Vnode类实例化出来的对象进行分类,,例如注释节点,文本节点,元素节点,组件节点,函数式节点,克隆节点。

然后通过编译将模板转成渲染函数render,执行渲染函数render,在其中创建不同类型的Vnode类,最好整合就可以得到一个虚拟DOM(vnode),最后通过patch将vnode和oldVnode进行比较后,生成真实DOM

7、怎么理解Vue的单向数据流

  • 数据从父级组件传递给子组件,只能单向绑定
  • 子组件内部不能直接修改从父级传递过来的数据
  • 所有的prop都使得其父子prop之间形成了一个单向下行绑定:父级prop的更新会向下流动到子组件中,但是反过来则不行,这样会防止子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
  • 每次父级组件发生更新时,子组件中所有的prop都将会刷新为最新的值,这意味着你步应该在一个子组件内部改变prop。如果你这样做了,vue会在浏览器的控制台中发出警告
  • 子组件想修改时,只能通过$emit派发一个自定义事件,父组件接收到后,由父组件修改

8、SPA的理解,他的优缺点分别是什么

单页Web应用(single-page-applocation 简称为SPA)是一种特殊的WEB应用,它将所有的活动局限于一个Web页面中,仅在该Web页面初始化时加载相应的HTML、JavaScript和CSS,一旦页面加载完成了,SPA不会因为用户的操作而进行页面的重新加载或跳转,取而代之的是利用JavaScript动态的变换HTML的内容,从而实现UI与用户的交互,由于避免了页面的重新加载,SPA可以提供较为流畅的用户体验,得益于ajax,我们可以实现无跳转刷新,又多亏了浏览器的history机制,我们用hash的变化从而可以实现推动界面变化,从而模拟元素客户端的单页面切换效果:

SPA被人追捧是有道理的,但是他也又不足之处,当然任何东西都有两面性,

  • 优点
    • 无刷新界面,给用户体验原生的应用感觉
    • 节省原生app开发陈本
    • 提高发布效率,无需每次安装更新包
    • 容易借助其他知名平台更有利于营销和推广
    • 符合web2.0的趋势
  • 缺点
    • 效果和性能确实和原生的有较大差距
    • 各个浏览器的版本兼容性不一样
    • 业务随着代码量增加而增加,不利于首屏优化
    • 某些平台对hash有偏见,有些甚至不支持pushstate
    • 不利于搜索引擎抓取

9、你知道style上加scoped属性的原理嘛

1、什么是scoped

在vue组件中,为了使样式私有化(模块化),不对全局造成污染,可以在style标签上添加scoped属性以表示他的只属于当下的模块,局部有效。如果一个项目中的所有vue组件style标签全部加上了scoped,相当于实现了样式的私有化。如果引用了第三方组件,需要在当前组件中局部修改第三方组件的样式,而又不想去除scoped属性造成组件之间的样式污染,此时只能通过穿透scoped的方式来解决,选择器。

2、scoped的实现原理:

Vue 中的 scoped 属性的效果主要通过 PostCSS 转译实现,如下是转译前的 Vue 代码:

Vue.js scoped 浏览器渲染后的代码:

Vue.js scoped
.scoped[data-v-fed36922]{font-size:14px;} 即:PostCSS 给所有 dom 添加了一个唯一不重复的动态属性,然后,给 CSS 选择器额外添加一 个对应的属性选择器来选择该组件中 dom,这种做法使得样式私有化

10、jquery和params之间的区别是什么?

1、query要用path引入,params要用name来引入 2、接收参数时,分别是this.route.query.name和this.route.params.name(注意:是route而不是router) 3、query更加类似于我们ajax中get传参,parmas则类似于post,前者在浏览器的地址栏中显示,parmas不显示 4、parmas传值一刷新就没了,query传值刷新还存在

11、VUe-router的钩子函数都有哪些

关于vue-router中的钩子函数主要分为3类

1、全局钩子函数要包含beforeEach

beforeEach函数有三个参数,分别是

to:router即将进入的路由对象

from:当前导航即将离开的路由

next:function进行管道中的一个钩子,如果执行完了,则导航的状态就是confirmed(确认的)否则为false,终止导航

2、单独路由独享组件

beforeEnter

3、组件内钩子

beforeRouterEnter

beforeRouterUpdate

beforeRouterLeave