vue面试题目

  • vue数据
    • 1. 说一下Vue的双向绑定数据的原理
    • 2. 解释单向数据流和双向数据绑定
    • 3. Vue 如何去除url中的
    • 4. 对 MVC、MVVM的理解
    • 5. 介绍虚拟DOM
    • 6. vue生命周期的理解
    • 7. 组件通信
    • 8. vue-router 路由实现
    • 9. v-if 和 v-show 区别
    • 10. $ route和$router的区别
    • 11. NextTick 是做什么的
    • 12. Vue 组件 data 为什么必须是函数
    • 13. 计算属性computed 和事件 methods 有什么区别
    • 14. 对比 jQuery ,Vue 有什么不同
    • Vue 中怎么自定义指令
    • 16. Vue 中怎么自定义过滤器
    • 17. 对 keep-alive 的了解
    • 18. Vue 中 key 的作用
    • 19. Vue 的核心是什么
    • 20. vue 等单页面应用的优缺点
    • 21. vue-router 使用params与query传参有什么区别
    • MVVM的设计思想的优势?
    • 事件传参
    • 自定义指令:directive
    • 计算属性:computed
    • 监听器:watch
    • 过滤器
    • 组件
      • 如何创建一个全局组件
      • 如何创建一个局部组件
      • 如何定义局部自定义指令
      • 如何定义局部过滤器
    • 组件传值
      • 父向子传值
      • 子向父传值
      • 兄弟组件传值
      • 跨组件传值
    • 组件插槽
    • Promise的使用
    • axios拦截器
    • 路由
    • 在vue中路由传参
    • 嵌套路由
    • 编程式导航
    • 路由钩子
    • vue脚手架的安装和使用
      • 命令行方式
      • ui界面方式
      • 安装element-ui
      • 使用element中select组件
    • 安装axios
    • vue动画
    • 利用类名添加动画
    • 结合css动画库设置动画
    • 加深面试题
      • 虚拟dom
      • Diff算法
      • axios配置代理服务器
      • 小程序分包加载
      • v-if和v-for避免结合使用
      • vue中route和router的区别
      • 如何封装一个插件
      • vueI18n的使用
    • keep-alive
      • 使用了本地存储为什么还使用vuex?
      • js
    • 重中之重、Vue的双向数据绑定原理是什么?
    • 一、什么是MVVM?
    • 二、mvvm和mvc区别?它和其它框架(jquery)的区别是什么?哪些场景适合?
    • 三、vue的优点是什么?
    • 四、 组件之间的传值?
    • 五、路由之间跳转
    • 六、vue.cli中怎样使用自定义的组件?有遇到过哪些问题吗?
    • 七、vue如何实现按需加载配合webpack设置
    • 八、vuex面试相关
      • (1)vuex是什么?怎么使用?哪种功能场景使用它?
      • (2)vuex有哪几种属性?
      • (3)不用Vuex会带来什么问题?
    • 九、 v-show和v-if指令的共同点和不同点
    • 十、 如何让CSS只在当前组件中起作用
    • 十一、的作用是什么?
    • 十二、Vue中引入组件的步骤?
    • 十三、指令v-el的作用是什么?
    • 十四、在Vue中使用插件的步骤
    • 十五、请列举出3个Vue中常用的生命周期钩子函数
    • 十六、active-class是哪个组件的属性?
    • 十七、怎么定义vue-router的动态路由以及如何获取传过来的动态参数?
    • 十八、vue-router有哪几种导航钩子?
    • 十九、生命周期相关面试题
      • (1)、什么是vue生命周期
      • (2)、vue生命周期的作用是什么
      • (3)、vue生命周期总共有几个阶段
      • (4)、第一次页面加载会触发哪几个钩子
      • (5)、DOM 渲染在 哪个周期中就已经完成
      • (6)、简单描述每个周期具体适合哪些场景
    • 二十、说出至少4种vue当中的指令和它的用法?
    • 二十一、vue-loader是什么?使用它的用途有哪些?
    • 二十二、scss是什么?在vue.cli中的安装使用步骤是?有哪几大特性?
    • 二十三、为什么使用key?
    • 二十四、为什么避免 v-if 和 v-for 用在一起
    • 二十五、VNode是什么?虚拟 DOM是什么?
    • 二十六、vue-loader是什么?使用它的用途有哪些?
    • 二十八、vue.cli中怎样使用自定义的组件?有遇到过哪些问题吗?
    • 二十九、聊聊你对Vue.js的template编译的理解?

前言
作为前端开发中现行最火的框架之一,Vue 在面试中出现的频率不断增加。基于此,总结了一些 Vue 方面经常出现的面试题,留给自己查看消化,也分享给有需要的小伙伴

感兴趣的小伙伴也可以点击 这里,查看前端方面的其他面试题,欢迎 star 关注

如果文章中有出现纰漏、错误之处,还请看到的小伙伴留言指正,先行谢过

以下 ↓

vue数据

1. 说一下Vue的双向绑定数据的原理

vue 实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的 settergetter,在数据变动时发布消息给订阅者,触发相应监听回调。

2. 解释单向数据流和双向数据绑定

单向数据流: 顾名思义,数据流是单向的。数据流动方向可以跟踪,流动单一,追查问题的时候可以更快捷。缺点就是写起来不太方便。例如:在父向子传值的时候,如果改变父组件的值,子组件会跟着同步更新,反之不允许
要使UI发生变更就必须创建各种 action 来维护对应的 state双向数据绑定:数据之间是相通的,将数据变更的操作隐藏在框架内部。优点是在表单交互较多的场景下,会简化大量与业务无关的代码。缺点就是无法追踪局部状态的变化,增加了出错时 debug 的难度。例如:v-model,数据发生变化,同步视图,视图发生变化,同步数据

3. Vue 如何去除url中的

vue-router 默认使用 hash 模式,所以在路由加载的时候,项目中的 url 会自带 #。如果不想使用 #, 可以使用 vue-router 的另一种模式 history

new Router({mode: 'history',routes: [ ]
})

需要注意的是,当我们启用 history 模式的时候,由于我们的项目是一个单页面应用,所以在路由跳转的时候,就会出现访问不到静态资源而出现 404 的情况,这时候就需要服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面。

4. 对 MVC、MVVM的理解

MVC

特点:

View 传送指令到 Controller
Controller 完成业务逻辑后,要求 Model 改变状态
Model 将新的数据发送到 View,用户得到反馈
所有通信都是单向的

MVVM

特点:

各部分之间的通信,都是双向的
采用双向绑定:View 的变动,自动反映在 ViewModel,反之亦然
具体请移步 这里

5. 介绍虚拟DOM

参考这里

6. vue生命周期的理解

vue实例有一个完整的生命周期,生命周期也就是指一个实例从开始创建到销毁的这个过程
生命周期:是指一个对象从创建到运行到销毁的整个过程,被称为生命周期

生命周期函数:在不同的生命周期阶段会自动执行对应的函数,而这些函数则被成为生命周期函数

// 创建阶段beforeCreate() {// 这个生命周函数,代表开始创建实例了console.log('beforeCreate',this.num)},created () {// 代表数据和方法已经初始化成功了,此处dom还没有挂载到页面上console.log('created',this.num,this.$el)},beforeMount () {// 挂在之前console.log('beforeMount',this.$el)},mounted () {// dom已经挂载了console.log('mounted',this.$el)},// 运行更新阶段beforeUpdate () {// 数据更新,页面还没有同步console.log('beforeUpdated',this.num,document.getElementById('app').innerHTML)},updated () {// 数据更新,页面已经同步console.log('updated',this.num,document.getElementById('app').innerHTML)},// 销毁阶段beforeDestroy () {// 销毁之前console.log('beforeDestroy')},destroyed () {// 已经销毁了console.log('destroy')}
beforeCreate() 在实例创建之间执行,数据未加载状态
created() 在实例创建、数据加载后,能初始化数据,dom渲染之前执行
beforeMount() 虚拟dom已创建完成,在数据渲染前最后一次更改数据
mounted() 页面、数据渲染完成,真实dom挂载完成
beforeUpadate() 重新渲染之前触发
updated() 数据已经更改完成,dom 也重新 render 完成,更改数据会陷入死循环
beforeDestory() 和 destoryed() 前者是销毁前执行(实例仍然完全可用),后者则是销毁后执行

7. 组件通信

1、父组件向子组件通信
子组件通过 props 属性,绑定父组件数据,实现双方通信

2、子组件向父组件通信
将父组件的事件在子组件中通过 $emit 触发

3、非父子组件、兄弟组件之间的数据传递

/*新建一个Vue实例作为中央事件总嫌*/
let event = new Vue();/*监听事件*/
event.$on('eventName', (val) => {//......do something
});/*触发事件*/
event.$emit('eventName', 'this is a message.')

Vuex 数据管理,也可以通过vuex全局状态管理器去实现。

8. vue-router 路由实现

路由就是用来跟后端服务器进行交互的一种方式,通过不同的路径,来请求不同的资源,请求不同的页面是路由的其中一种功能
参考 这里

9. v-if 和 v-show 区别

使用了 v-if 的时候,如果值为 false ,那么页面将不会有这个 html 标签生成。
v-show 则是不管值为 true 还是 falsehtml 元素都会存在,只是 CSS 中的 display 显示或隐藏

10. $ route和$router的区别

$routerVueRouter 实例,想要导航到不同 URL,则使用 $router.push 方法$route 为当前 router 跳转对象里面可以获取 namepathqueryparams

11. NextTick 是做什么的

$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM
具体可参考官方文档 深入响应式原理

12. Vue 组件 data 为什么必须是函数

因为js本身的特性带来的,如果 data 是一个对象,那么由于对象本身属于引用类型,当我们修改其中的一个属性时,会影响到所有Vue实例的数据。如果将 data 作为一个函数返回一个对象,那么每一个实例的 data 属性都是独立的,不会相互影响了

13. 计算属性computed 和事件 methods 有什么区别

我们可以将同一函数定义为一个 method 或者一个计算属性。对于最终的结果,两种方式是相同的

不同点:

computed: 计算属性是基于它们的依赖进行缓存的,只有在它的相关依赖发生改变时才会重新求值对于 method ,只要发生重新渲染,method 调用总会执行该函数

14. 对比 jQuery ,Vue 有什么不同

jQuery 专注视图层,通过操作 DOM 去实现页面的一些逻辑渲染; Vue 专注于数据层,通过数据的双向绑定,最终表现在 DOM 层面,减少了 DOM 操作Vue 使用了组件化思想,使得项目子集职责清晰,提高了开发效率,方便重复利用,便于协同开发

Vue 中怎么自定义指令

全局注册

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {// 当被绑定的元素插入到 DOM 中时……inserted: function (el) {// 聚焦元素el.focus()}
})

局部注册

directives: {focus: {// 指令的定义inserted: function (el) {el.focus()}}
}

参考 官方文档-自定义指令

16. Vue 中怎么自定义过滤器

可以用全局方法 Vue.filter() 注册一个自定义过滤器,它接收两个参数:过滤器 ID 和过滤器函数。过滤器函数以值为参数,返回转换后的值

Vue.filter('reverse', function (value) {return value.split('').reverse().join('')
})
<!-- 'abc' => 'cba' -->
<span v-text="message | reverse"></span>

过滤器也同样接受全局注册和局部注册

17. 对 keep-alive 的了解

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

<keep-alive><component><!-- 该组件将被缓存! --></component>
</keep-alive>

可以使用API提供的props,实现组件的动态缓存
具体参考 官方API
也可移步 这里

18. Vue 中 key 的作用

key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用 key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误
具体参考 官方API

19. Vue 的核心是什么

数据驱动 组件系统

20. vue 等单页面应用的优缺点

优点:

  • 良好的交互体验
  • 良好的前后端工作分离模式
  • 减轻服务器压力

缺点:

  • SEO难度较高
  • 前进、后退管理
  • 初次加载耗时多

21. vue-router 使用params与query传参有什么区别

vue-router 可以通过 paramsquery 进行传参

// 传递
this.$router.push({path: './xxx', params: {xx:xxx}})
this.$router.push({path: './xxx', query: {xx:xxx}})// 接收
this.$route.paramsthis.$route.query
  • params 是路由的一部分,必须要有。query 是拼接在 url 后面的参数,没有也没关系
  • params 不设置的时候,刷新页面或者返回参数会丢,query 则不会有这个问题

MVVM的设计思想的优势?

双向绑定技术,当Model变化时,View也会自动变化,view发生更新,model也跟着同步
我们减少了dom的操作,因为我们只需要关注数据就可以
mvvm的设计思想大大提高了代码的耦合性

事件传参

没有传递参数,事件函数的默认第一个参数是事件对象
如果传递了参数,事件函数就没有了默认参数,全部变为对应位置的实参的形参,就没有了事件对象
既有自己传的的参数,也有事件对象,通过$event传递事件对象,在事件函数内部通过通过对应位置的形参来接收事件对象,传递刀了event没有强制性的位置,但是建议放在最后

自定义指令:directive

文档

为什么自定义指令?

vue提供的系统指令满足不了我们的需求,那么我们就需要自定义指令

通过Vue.directive进行自定义指令的定义

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。

计算属性:computed

定义的时候是一个方法,使用的时候当作属性使用

只要return后面的数据发生变化,该计算属性就会重新计算

计算属性具有缓存功能

监听器:watch

watch侦听器如果监听的是一个对象,需要开启深度监听

watch:{num:{// 监听数据发生变化的处理函数handler(newNum) {console.log(newNum)},// 是否开启深度监听deep: true}
}

过滤器

<div id="app"><div>{{ date | formatDate('-')}}</div><div>{{ date | formatDate('/')}}</div></div><script src="vue.js"></script><script>Vue.filter('formatDate',(data,line)=>{console.log(data,line)const y = data.getFullYear()const m = (data.getMonth()+1).toString().padStart(2,0)const d = data.getDate().toString().padStart(2,0)return y+line+m+line+d})new Vue({el: '#app',data:{date: new Date}})</script>

组件

如何创建一个全局组件

通过Vue.component来创建一个全局组件,第一个参数是组件名字,第二个参数是组件的配置对象,可以通过template配置组件的结构,data定义数据等等

为什么组件内部的data是一个函数?

为了保证组件在每次使用的时候保证数据是当前组件唯一的,互不影响

如何创建一个局部组件

在组件内部通过components来创建一个局部组件

全局组件和局部组件的区别

局部组件:只能在当前的父组件中使用

全局组件: 在任意地方使用

如何定义局部自定义指令

在组件内部通过directives来创建一个局部指令

全局指令和局部指令的区别

局部指令:只能在当前的组件中使用

全局指令: 在任意地方使用

如何定义局部过滤器

在组件内部通过filters来创建一个局部过滤器

全局过滤器和局部过滤器的区别

局部过滤器:只能在当前的组件中使用

全局过滤器: 在任意地方使用

组件传值

父向子传值

  • 父亲怎么传:通过属性绑定形式传
  • 儿子怎么接收:通过props来接收

子向父传值

  • 子怎么传:通过this.$emit触发一个自定义事件,并且发送一个值
  • 父怎么接收:通过定义自定义事件的事件函数的形参来接收

兄弟组件传值

定义一个事件中心,或者是第三方

接收值的组件:通过该事件中心的$on来定义自定义事件的事件函数来接收值

eventBus.$on('getTab1',(data)=>{console.log('接收tab1传递的值',data)
})

另一个兄弟组件怎么传:通过事件中心的$emit触发对应的 刀了 on的事件,并且把值传递过去

eventBus.$emit('getTab1',this.num)

跨组件传值

Vue.component('my-sub1',{template:'#my-sub1',data() {return {money: 10000000}},provide:{money:1000},components:{'sub-a':{template:'<div>子组件<sub-b></sub-b></div>',components:{'sub-b':{template:'<div>子组件{{money}}</div>',inject:['money']}}}}})new Vue({el: '#app'})

组件插槽

  • 默认插槽:

    • 在组件标签中间可以传递一些子节点
    • 组件内部利用slot标签进行接收
  • 具名插槽

    • 在组件标签中间通过定义slot的名字传递子节点
<my-banner><div slot="header">头部</div><div slot="footer">底部</div>
</my-banner>
  • 组件内部利用slot的name进行对应接收
<template id="banner"><div><slot name="header"></slot><slot name="footer"></slot></div>
</template>
  • 作用域插槽

    • 在组件内部定义数据,将数据传递给插槽的结构
    • 通过给slot动态绑定属性
<template id="my-li"><ul><li v-for="item in arr"><slot :row="item"></slot></li></ul></template>

插槽内部:通过slot-scope=“scope”来接收

<my-li><template slot-scope="scope"><p>{{scope.row}}</p></template>
</my-li>
<my-li><template slot-scope="scope"><a href="04-侦听器.html">{{scope.row}}</a>        </template>
</my-li>

Promise的使用

利用Promise处理异步解决回调地狱的问题

Promise的all的方法

Promise的race的方法

面试题:

现在有三个接口地址,需要三个接口地址请求完事之后进行下一步的逻辑处理(不一定按顺序请求完成)

// .then回调
axios.get('http://xxx').then(res=>{console.log(res)axios.get('http://xxx').then(res=>{console.log(res)axios.get('http://xxx').then(res=>{console.log(res)})})
})// .then返回新的Promise继续调用.then
axios.get('xxx').then(res=>{return axios.get('xxx')
}).then(res=>{return axios.get('xxx')
}).then(res=>{console.log('三个请求完事')
})// async await
const asyncHandle = async function(){const res1 = await axios.get('http://xxx1')const res2 = await axios.get('http://xxx2')const res3 = await axios.get('http://xxx3')console.log(res1,res2,res3)
}asyncHandle()
// Promise all方法
const getComments = new Promise(()=>{axios.get('http://xxx')
})Promise.all([axios.get('http://xxx1'),axios.get('http://xxx2'),axios.get('http://xxx3')
]).then(res=>{console.log(res)
})

axios拦截器

请求拦截

axios.interceptors.request.use

响应拦截

axios.interceptors.response.use

路由

什么是路由?

路由就是对应关系,组件和url地址,根据不同的地址显示不同的组件,路由也是实现spa(单页面应用程序)的主要核心,因为单页面应用程序,就是只有一个html,在这个html里面切换组件,根据url,例如地址为/home,在这个页面中就显示home组件

前端路由:url和组件

后端路由:根据不同的地址请求不同的接口

路由

在vue中路由传参

  • params传参

在跳转的时候可以通过/home/10

路由规则:

new VueRouter({routes: [{path: '/home/:id',component: Home}]
})

组件内部怎么来接收参数

this.$route.params.id
  • query传参

在跳转的时候可以通过/home?id=10

组件内部怎么来接收参数

this.$route.query.id

​路由history模式注意的问题

嵌套路由

编程式导航

路由钩子

全局钩子:都会对所有的路由进行拦截

beforeEach:进入之前

afterEach:已经进入了

路由独享钩子:可以针对某一个路由进行拦截,这个需要写在路由规则里

 {path: '/',name: 'home',beforeEnter: (to,from,next)=>{console.log('即将进入home')},component: Home}

组件内的守卫:

针对组件进行拦截

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

vue脚手架的安装和使用

命令行方式

配置文档

利用vue.config.js关闭esLint

ui界面方式

文档

安装element-ui

安装vue-cli-plugin-element插件

使用element中select组件

注册组件

import Vue from 'vue'
import { Button, Select } from 'element-ui'Vue.use(Button)
Vue.use(Select)

使用组件

<el-select v-model="value" placeholder="请选择"><el-optionv-for="item in options":key="item.value":label="item.label":value="item.value"></el-option></el-select>

复制数据

 options: [{value: '选项1',label: '黄金糕'}, {value: '选项2',label: '双皮奶'}, {value: '选项3',label: '蚵仔煎'}, {value: '选项4',label: '龙须面'}, {value: '选项5',label: '北京烤鸭'}],value: ''

安装axios

安装依赖》运行依赖》axios
使用axios发送请求
利用Vue.prorotype挂载到原型上

vue动画

文档

利用类名添加动画

在进入/离开的过渡中,会有 6 个 class 切换。

v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。
首先给需要添加动画的元素用transition包裹起来

利用类名实现动画

.v-enter,.v-leave-to{transform: translate(200px,0)
}
.v-enter-active,.v-leave-active{transition: transform 1s;
}
.v-enter-to,.v-leave{transform: translate(0,0)
}

自定义动画类名

<transition name="box2"><div class="box" v-show="flag"></div>
</transition>
.box2-enter,.box2-leave-to{opacity: 0;
}
.box2-enter-active,.box2-leave-active{transition: opacity 1s;
}
.box2-enter-to,.box2-leave{opacity: 1;
}

结合css动画库设置动画

引入css动画库

通过enter-active-classleave-active-class设置动画

<transitionenter-active-class="animated bounceIn"leave-active-class="animated bounceOut"><div class="box" v-show="flag"></div>
</transition>

加深面试题

虚拟dom

本质上就是一个JS对象,用来描述你希望在屏幕上看到的内容

Diff算法

虚拟dom高效更新执行过程

  • 初次渲染时,会根据model数据创建一个虚拟DOM对象(树)
  • 根据虚拟DOM生成真正的DOM,渲染到页面
  • 当数据变化后,会重新根据新的数据,创建新的虚拟DOM对象(树)
  • 与上一次得到的虚拟DOM对象,使用Diff算法比对(找不同),得到需要更新的内容
  • 最终,React只将变化的内容更新(patch)到DOM中,重新渲染到页面
  • 什么是虚拟dom:用js对象来表示页面上dom元素的的样式体现
  • 虚拟dom的作用:高效更新页面,还有就是让react脱离了浏览器的概念
  • 怎么来高效更新页面的:就是在第一次渲染页面的时候生成一份初始的虚拟dom树,然后当数据改变之后,再生成一份虚拟dom树,然后根据新旧dom树进行对比,对比完成之后,把有区别的进行更新
  • diff算法的作用就是:新旧虚拟dom树在对比的时候就是通过diff算法来对比的
  • diff算法又是怎么去对比的:tree diff、component diff、element diff

面试语术:

你知道虚拟dom吗?简单又谈一下?

虚拟dom可以实现高效更新,(后面如果自己能说一气说出来)

如何实现高效更新的?

利用新旧虚拟dom树进行对比,从而进行局部进行更新

如何进行新旧dom树进行对比?

利用diff算法,主要是tree diff树对比,component diff 组件对比,element diff 元素对比

加上一些其他话术

所以虚拟dom在前端中不管是vue、react等等都采用

axios配置代理服务器

什么是跨域?

在浏览器里面域名、端口、ip地址、协议,有任何一项不同,则跨域

A网站:http://localhost:8080/#/

B网站:http://localhost:3000/#/

处理跨域的方式?

JsonP(只能处理get请求)、cors(后端开启)、代理服务器

module.exports = {devServer: {host: 'localhost',port: 8080,proxy: {'/api': {target: 'http://localhost:3000',// 要跨域的域名changeOrigin: true, // 是否开启跨域},'/get': {target: 'http://localhost:3000',// 要跨域的域名changeOrigin: true, // 是否开启跨域}}}
}

小程序分包加载

某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。

在构建小程序分包项目时,构建会输出一个或多个分包。每个使用分包小程序必定含有一个主包。所谓的主包,即放置默认启动页面/TabBar 页面,以及一些所有分包都需用到公共资源/JS 脚本;而分包则是根据开发者的配置进行划分。

在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示。

目前小程序分包大小有以下限制:

整个小程序所有分包大小不超过 12M
单个分包/主包大小不能超过 2M
对小程序进行分包,可以优化小程序首次启动的下载时间,以及在多团队共同开发时可以更好的解耦协作。

代码演示,分包加载之前

pages: ['pages/tabs/home','pages/tabs/cates','pages/tabs/search','pages/tabs/cart','pages/tabs/my','pages/goods_list','pages/goods_detail/main','pages/order','pages/orderList'
]

抽离之后

pages: ['pages/tabs/home','pages/tabs/cates','pages/tabs/search','pages/tabs/cart','pages/tabs/my','pages/order','pages/orderList'],subpackages: [{name: 'goods',root: 'goods',pages: ['goods_list','goods_detail/main']}]

图片或者图标等资源文件使用线上资源

v-if和v-for避免结合使用

因为v-for的优先级大于v-if,所以会先根据所有数据生成结构,然后在根据,v-if进行按需渲染

<div id="app"><ul><li v-for="item in arr" v-if="item%2===0">{{ item }}</li></ul></div><script src="./vue.js"></script><script>new Vue({el: '#app',data: {arr: [1,2,3,4]}})</script>

我们可以采用计算属性来避免此问题,这样的话,先通过计算属性,计算出要渲染的数据,然后直接循环计算属性即可

<div id="app"><ul><li v-for="item in newArr">{{ item }}</li></ul></div><script src="./vue.js"></script><script>new Vue({el: '#app',data: {arr: [1,2,3,4]},computed: {newArr() {return this.arr.filter(item=>{return item%2===0})}}})</script>

vue中route和router的区别

route是当前路由信息,可以获取到当前路由地址参数等等
router是全局路由实例对象,可以通过router进行路由的跳转后退等等

如何封装一个插件

定义一个button组件,在index.js中引入并注册

在components中创建一个index.js

import sgButton from './button.vue'
function install (Vue) {Vue.component(sgButton.name, sgButton)
}export default {install
}

在main.js中导入该js文件,当调用Vue.use方法,会默认调用内部的install方法

面试题

你有封装过插件吗? Vue.use的原理是什么?

当调用Vue.use方法,会默认调用内部的install方法,install这个方法默认的第一个形参就是Vue,这样的话我们就可以通过Vue注册一些全局组件,给Vue扩展一下方法。

vueI18n的使用

vue中实现语言切换的方式如何实现的

1.NPM 项目安装

cnpm i vue-i18n

2.使用方法

/* 国际化使用规则 */
import Vue from 'vue'
import VueI18n from 'vue-i18n'Vue.use(VueI18n)
<!-- 需要国际化的数据定义在此处 -->
const messages = {en: {message: {hello: 'world hello'}},zh: {message: {hello: '世界'}}
}
<!-- 使用i18n -->
const i18n = new VueI18n({locale: 'zh',messages
})export default {data () {return {hello: this.$t('message.hello')}},i18n
}

3.页面数据使用

<div id="#app"><p>{{ $t("message.hello") }}</p>
</div>
1
2
3
4.案例练习定义基本结构
<div id="app"><button>切换语言</button><ul><li>首页</li><li>新闻</li><li>关于</li><li>概况</li></ul>
</div>
ul{list-style: none;li{width: 20%;height: 70px;line-height: 70px;background: green;color: #fff;float: left;margin-left: 2%;text-align: center;line-height: 70px;}
}

定义语言包
zh.js

export default {nav: ['首页', '新闻', '概况', '关于']
}

en.js

export default {nav: ['home', 'news', 'gk', 'about']
}

在main.js中引入语言包

import zh from './i18n/zh.js'
import en from './i18n/en.js'
Vue.use(VueI18n)const i18n = new VueI18n({locale: 'en',messages: {zh,en}
})

数据渲染和切换

<template><div id="app"><button @click="changeLang">切换语言</button><ul><li v-for="(item, index) in $t('nav')" :key="index">{{ item }}</li></ul></div>
</template><script>
export default {methods: {changeLang () {this.$i18n.locale = this.$i18n.locale === 'en' ? 'zh' : 'en'}}
}
</script>

keep-alive

使用了本地存储为什么还使用vuex?

vuex的数据是响应式的,而本地存储的数据不是响应式的,使用本地存储是为了让数据持久化

js

js静态成员和实例成员

静态成员:静态成员 在构造函数本身上添加的成员 如下列代码中 sex 就是静态成员,静态成员只能通过构造函数来访问

实例成员:实例成员就是构造函数内部通过this添加的成员 如下列代码中uname age sing 就是实例成员,实例成员只能通过实例化的对象来访问

重中之重、Vue的双向数据绑定原理是什么?

答:vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
具体步骤:
第一步:需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter
这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
1、在自身实例化时往属性订阅器(dep)里面添加自己
2、自身必须有一个update()方法
3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
第四步:MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。

一、什么是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 来统一管理。

二、mvvm和mvc区别?它和其它框架(jquery)的区别是什么?哪些场景适合?

mvc和mvvm其实区别并不大。都是一种设计思想。主要就是mvc中Controller演变成mvvm中的viewModel。mvvm主要解决了mvc中大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。
区别:vue数据驱动,通过数据来显示视图层而不是节点操作。
场景:数据操作比较多的场景,更加便捷

三、vue的优点是什么?

低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。

四、 组件之间的传值?

父组件与子组件传值
父组件通过标签上面定义传值
子组件通过props方法接受数据
子组件向父组件传递数据
子组件通过$emit方法传递参数

五、路由之间跳转

声明式(标签跳转) 编程式( js跳转)

六、vue.cli中怎样使用自定义的组件?有遇到过哪些问题吗?

第一步:在components目录新建你的组件文件(indexPage.vue),script一定要export default {}
第二步:在需要用的页面(组件)中导入:import indexPage from ‘@/components/indexPage.vue’
第三步:注入到vue的子组件的components属性上面,components:{indexPage}
第四步:在template视图view中使用,
例如有indexPage命名,使用的时候则index-page

七、vue如何实现按需加载配合webpack设置

webpack中提供了require.ensure()来实现按需加载。以前引入路由是通过import 这样的方式引入,改为const定义的方式进行引入。
不进行页面按需加载引入方式:import home from ‘…/…/common/home.vue’
进行页面按需加载的引入方式:
const home = r => require.ensure( [], () => r (require(’…/…/common/home.vue’)))

八、vuex面试相关

(1)vuex是什么?怎么使用?哪种功能场景使用它?

vue框架中状态管理。在main.js引入store,注入。新建一个目录store,…… export 。场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车

(2)vuex有哪几种属性?

有五种,分别是 State、 Getter、Mutation 、Action、 Module
vuex的State特性
A、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于一般Vue对象里面的data
B、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
C、它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中
vuex的Getter特性
A、getters 可以对State进行计算操作,它就是Store的计算属性
B、 虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用
C、 如果一个状态只在一个组件内使用,是可以不用getters
vuex的Mutation特性
Action 类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态;Action 可以包含任意异步操作。

(3)不用Vuex会带来什么问题?

可维护性会下降,想修改数据要维护三个地方;
可读性会下降,因为一个组件里的数据,根本就看不出来是从哪来的;
增加耦合,大量的上传派发,会让耦合性大大增加,本来Vue用Component就是为了减少耦合,现在这么用,和组件化的初衷相背。

九、 v-show和v-if指令的共同点和不同点

v-show指令是通过修改元素的display的CSS属性让其显示或者隐藏
v-if指令是直接销毁和重建DOM达到让元素显示和隐藏的效果

十、 如何让CSS只在当前组件中起作用

将当前组件的

十一、的作用是什么?

包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。

十二、Vue中引入组件的步骤?

1)采用ES6的import … from …语法或CommonJS的require()方法引入组件
2)对组件进行注册,代码如下

// 注册
Vue.component('my-component', {template: '<div>A custom component!</div>'
})

3)使用组件

十三、指令v-el的作用是什么?

提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标.可以是 CSS 选择器,也可以是一个 HTMLElement 实例

十四、在Vue中使用插件的步骤

采用ES6的import … from …语法或CommonJSd的require()方法引入插件
使用全局方法Vue.use( plugin )使用插件,可以传入一个选项对象Vue.use(MyPlugin, { someOption: true })

十五、请列举出3个Vue中常用的生命周期钩子函数

created: 实例已经创建完成之后调用,在这一步,实例已经完成数据观测, 属性和方法的运算, watch/event事件回调. 然而, 挂载阶段还没有开始, e l 属 性 目 前 还 不 可 见 m o u n t e d : e l 被 新 创 建 的 v m . el属性目前还不可见 mounted : el被新创建的 vm.el属性目前还不可见mounted:el被新创建的vm.el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
activated: keep-alive组件激活时调用

十六、active-class是哪个组件的属性?

vue-router模块的router-link组件。

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

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

十八、vue-router有哪几种导航钩子?

三种,一种是全局导航钩子:router.beforeEach(to,from,next),作用:跳转前进行判断拦截。
第二种:组件内的钩子;
第三种:单独路由独享组件

十九、生命周期相关面试题

总共分为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结构依然存在

(1)、什么是vue生命周期

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

(2)、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

二十、说出至少4种vue当中的指令和它的用法?

v-if:判断是否隐藏;v-for:数据循环;v-bind:class:绑定一个属性;v-model:实现双向绑定

二十一、vue-loader是什么?使用它的用途有哪些?

解析.vue文件的一个加载器。
用途:js可以写es6、style样式可以scss或less、template可以加jade等

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

答:css的预编译。
使用步骤:
第一步:先装css-loader、node-loader、sass-loader等加载器模块
第二步:在build目录找到webpack.base.config.js,在那个extends属性中加一个拓展.scss
第三步:在同一个文件,配置一个module属性
第四步:然后在组件的style标签加上lang属性 ,例如:lang=”scss”
特性:
可以用变量,例如($变量名称=值);
可以用混合器,例如()
可以嵌套

二十三、为什么使用key?

当有相同标签名的元素切换时,需要通过 key 特性设置唯一的值来标记以让 Vue 区分它们,否则 Vue 为了效率只会替换相同标签内部的内容。

二十四、为什么避免 v-if 和 v-for 用在一起

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

二十五、VNode是什么?虚拟 DOM是什么?

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

二十六、vue-loader是什么?使用它的用途有哪些?

答:解析.vue文件的一个加载器,跟template/js/style转换成js模块。
用途:js可以写es6、style样式可以scss或less、template可以加jade等

二十七、请说出vue.cli项目中src目录每个文件夹和文件的用法?
答:assets文件夹是放静态资源;components是放组件;router是定义路由相关的配置;view视图;app.vue是一个应用主组件;main.js是入口文件

二十八、vue.cli中怎样使用自定义的组件?有遇到过哪些问题吗?

答:
第一步:在components目录新建你的组件文件(smithButton.vue),script一定要export default {
第二步:在需要用的页面(组件)中导入:import smithButton from ‘…/components/smithButton.vue’
第三步:注入到vue的子组件的components属性上面,components:{smithButton}
第四步:在template视图view中使用,
问题有:smithButton命名,使用的时候则smith-button。

二十九、聊聊你对Vue.js的template编译的理解?

答:简而言之,就是先转化成AST树,再得到的render函数返回VNode(Vue的虚拟DOM节点)
详情步骤:
首先,通过compile编译器把template编译成AST语法树(abstract syntax tree 即 源代码的抽象语法结构的树状表现形式),compile是createCompiler的返回值,createCompiler是用以创建编译器的。另外compile还负责合并option。
然后,AST会经过generate(将AST语法树转化成render funtion字符串的过程)得到render函数,render的返回值是VNode,VNode是Vue的虚拟DOM节点,里面有(标签名、子节点、文本等等)

vue面试题目(更新版)相关推荐

  1. 2020社招前端VUE面试题目

    2020前端VUE面试题目集锦 年初由于疫情影响导致上家公司不景气,也由于自己一系列的考虑决定裸辞找工作,面试了十多家公司,最终进入了比较心仪的公司,我将这段时间面试所遇见的和VUE先关题目大概做个整 ...

  2. 前端工程师必须知道的vue前端面试题目汇总

    ①:说说Vue和Angular.ReactJS的相同点和不同点 ②:简单描述一下Vue中的MVVM模型 ③:v-if和v-show指令有什么区别? ④:如何阻止Vue中的绑定事件不发生冒泡 ⑤:父.子 ...

  3. 2018年中高级前端面试题目小结

    2018年中高级前端面试题目小结 前言 关于前端面试,及面试题目,我之前有很多文章总结过,可以在右侧搜索面试,进行查找.其实面试中可以问的问题很多,最近几年,我也面试过很多工作2-4年的前端,我一般会 ...

  4. BAT等公司高薪招聘Android开发面试题目集锦

    整理过的50道面试题目 1.listView的优化方式 重用convertView viewHolder static class viewHolder 在列表里面有图片的情况下,监听滑动不加载图片 ...

  5. 2021-06-21 小米前端实习电话面试题目

    小米前端实习电话面试题目整理 自我介绍 说一下css的优先级 盒子水平居中和垂直居中 1. 定位 2. CSS3 3.flex 4.display: table-cell 说一下防抖和节流 JS的事件 ...

  6. android面试题目

    最近才开的博客,希望大家多多关注,andorid开发也做了3年有余了,也面试多家企业,借此机会分享一下,我们中遇到过的问题以及解决方案吧,希望能够对正在找工作的andoird程序员有一定的帮助.学完& ...

  7. 2021年Java面试题目最新总结【90%面试会踩的坑】

    学会java技术之后大家面临的最多的问题就是面试这关,求职面试java岗位是否能够成功是直接影响我们的工作机会的,所以对于Java程序员面试你准备好了吗?今天小编汇总了一下关于Java程序员面试,90 ...

  8. ​2019年最新华为、BAT、美团、头条、滴滴面试题目及答案汇总

    作者 | 苏克1900 来源 | 高级农民工(ID:Mocun6) [导语]最近 GitHub 上一个库火了,总结了 阿里.腾讯.百度.美团.头条等国内主流大厂的技术面试题目,目前 Star 2000 ...

  9. java简单的面试题目_简单的面试题目,大跌眼镜的结果

    原标题:简单的面试题目,大跌眼镜的结果 大老远跑来面试,总不能聊几句就走人吧.碍于情面,起码也得聊上十几分钟.招聘高峰这种情况尤甚,浪费你我时间.所以越来越多的组织会采用电话面试的方式,进行初步筛选. ...

最新文章

  1. 转】windows下使用批处理脚本实现多个版本的JDK切换
  2. 如何合并多个Django项目?
  3. angle-class
  4. 【译】ICO 2.0 — The Advent of What Crypto-Fund Raising Should Really Look Like
  5. 请教 Discuz syscache 中一段cache 的意思
  6. 全面认识UML类图元素
  7. 别让自己成为一名废弃的程序员
  8. python处理select
  9. Android 四大组件学习之Activity三
  10. 外贸客户如何跟进?外贸客户类型及跟进策略
  11. flash如何同时访问本地文件系统和网络文件
  12. 计算机usb接口失灵,电脑usb接口没反应,教您电脑usb接口没反应怎么解决
  13. flv网页播放器开源代码
  14. 爱情婚姻 - 苏格拉底
  15. webpack stats
  16. 【MySQL】在线无锁无延迟DDL神器gh-ost
  17. 金融量化 — 配对交易策略 (Pair Trading)
  18. 初创网络游戏公司运维遇到问题
  19. evolution邮箱_b2evolution简介
  20. mysql一次count多个字段_SQL一次查出多个字段的COUNT值

热门文章

  1. 学习 Golang 开发,需要掌握这几个开源框架
  2. 网站商务BD(Bussiness Development--商务拓展)
  3. 从设计的角度看 Redux
  4. ROS小车-上位机代码:两驱小车直线行走校准
  5. 机械硬盘计算机管理,机械硬盘怎么分区
  6. Google 不想与甲骨文争了,要放弃 Java APIs
  7. /usr/bin/ld:找不到 -lxxx
  8. Mac:Permission denied XXX
  9. NLP入门(八)使用CRF++实现命名实体识别(NER)
  10. 关于Img标签绑定:src不显示图片