VUE基础面试题

50道Vue常见面试题集锦,涵盖入门到精通,自测 Vue 掌握程度

Featured image

一、路由

1、Vue-router 路由有哪些模式

一般有两种模式
        1hash 模式后面的 hash 值的变化浏览器既不会向服务器发出请求浏览器也不会刷新每次 hash 值的变化会触发 hashchange 事件
        2history 模式利用了 HTML5 中新增的 pushState()  replaceState() 方法这两个方法应用于浏览器的历史记录栈在当前已有的 backforwardgo 的基础之上它们提供了对历史记录进行修改的功能只是当它们执行修改时虽然改变了当前的 URL但浏览器不会立即向后端发送请求

2、vue中$route和$router有什么区别?

this.$router 是 router 实例,也就是 router/index.js 中导出的那个对象,通过它可以调用 go、push方法进行页面跳转。
this.$route 表示当前访问的路由。通过 this.$route 可以获取到当前路由信息,比如获取当前路由的完整地址、query参数、params参数、meta信息等等。这个属性是只读的,不过可以通过 watch侦听到它的变化。

3、路由间是怎么跳转的,有哪些方式?

1、
2、this.$router.push()跳转到指定的 url,并添加一条历史记录。
3、this.$router.replace()跳转到指定的 url,但是不会增加一条历史记录。
4、this.$router.go(n)前进或后退 。

4、怎么定义vue-router的动态路由,怎么获取传过来的动态参数?

动态路由就是 路径参数

  1. 定义路由规则的时候,需要在path里面设置好 “斜线冒号变量”(/path/:id/:age)这种规则
  2. 当地址栏或跳转地址 和 路由规则匹配的时候,会进入对应的组件
  3. 组件中,通过 $route.params.参数名的语法获取参数值
类型 hash地址 路由规则 组件中获取参数值
路径参数(动态路由) /movie/3/绿皮书 { path: ‘/movie/:id/:name’ } $route.params.参数名

5、路由传参的方式和区别

: 
1方式params  query
2区别1params用的是name传递的参数在地址栏不会显示类似于post
        2query用的是path,传递的参数会在地址栏显示出来类似于get      
3举例说明
   1params 传参
     this.$router.push({
          name: 'particulars',
          params: {
            id: id
          }
        })
     this.$route.params.id
     
   2query传参
     this.$router.push({
          path: '/particulars',
          query: {
            id: id
          }
        })
      this.$route.query.id

二、生命周期

6、vue生命周期分为几个阶段?

Vue 实例从创建到销毁的过程,就是生命周期。
可以分为三个阶段:创建阶段、数据更新阶段、销毁阶段。
追问:创建阶段会执行哪些钩子函数?
答:创建阶段会依次执行 beforeCreate、created、beforeMount 和 mounted 4个钩子函数。
追问:更新阶段会执行哪些钩子函数?
答:更新阶段会依次执行 beforeUpdate 和 updated 两个钩子函数。
追问:销毁阶段会执行哪些钩子函数?
答:销毁阶段会依次执行 beforeDestroy和destroyed两个钩子函数。

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

当页面第一次加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子函数 。
如果是动态组件,并设置了缓存该组件,则还会触发 activated 钩子函数。

8、Vue 的父组件和子组件生命周期钩子函数执行顺序

1Vue 的父组件和子组件生命周期钩子函数执行顺序可以归类为以下 4 部分
  1加载渲染过程
      beforeCreate ->  created ->  beforeMount ->  beforeCreate ->  created ->  beforeMount ->  mounted ->  mounted
  2子组件更新过程
      beforeUpdate ->  beforeUpdate ->  updated ->  updated
  3父组件更新过程
      beforeUpdate ->  updated
  4销毁过程
   beforeDestroy ->  beforeDestroy ->  destroyed ->  destroyed

9、vue 钩子函数有哪些,有哪些使用的场景

1各阶段包含钩子 
		beforeCreate  在data数据注入到vm实例之前此时vm身上没有数据
    created       在data数据注入到vm实例之前此时vm身上有数据

    beforeMount   生成的结构替换视图之前此时DOM还没更新
    mounted       生成的结构替换视图之前此时DOM已经更新完成

    beforeUpdate  数据变化了dom更新之前
    updated       数据变化了dom更新之后
    
    activated     被keep-alive缓存的组件激活时调用
    deactivated   被keep-alive缓存的组件停用时调用

    beforeDestroy 实例销毁之前调用组件实例仍然可用
    destroyed     实例销毁之后调用

    这些钩子函数会在vue的生命周期的不同阶段自动被vue调用

2常用的钩子函数使用场景
    beforeCreate  做loading的一些渲染
    created       结束loading 发送数据的请求拿数据
    mounted       可以对dom进行操作
    updated       监视数据的更新
    beforeDestroy 销毁非vue资源防止内存泄漏例如清除定时器
    activated     当我们运用了组件缓存时如果想每次切换都发送一次请求的话需要把请求函数写在activated中而写在created或mounted中其只会在首次加载该组件的时候起作用

三、指令、方法、…

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

共同点:都可以通过条件控制元素的显示隐藏;
不同点:

  1. v-show通过display样式控制元素的显示和隐藏
  2. v-if 通过创建、移除元素控制元素的显示和隐藏
  3. 对于v-show而言,无论条件如何都会先创建元素,然后再通过display样式控制显示隐藏,有更高的初始渲染开销
  4. 如果用 v-if 频繁切换元素显示隐藏,就会不断的创建移除元素,开销很大。

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

Vue2中,v-for 比 v-if 具有更高的优先级。如果同时使用,那么当条件为false时,也会先完成遍历,遍历之后在根据条件判断是否显示,无疑会造成很多性能的浪费。比如下面的例子:

循环了1000次,结果一个都不需要显示。白白浪费性能
<div v-for="item in 1000" v-if="false">xxxxxxxxxxx</div>

参考链接:点这里

Vue3中,v-if 比 v-for 具有更高的优先级。如果同时使用,v-if 将不能使用v-for中的变量。比如:

先执行v-if ,条件是item < 100。但此时for还没执行呢拿不到item
<div v-for="item in 1000" v-if="item < 100">xxxxxxxxxxx</div>

参考链接:点这里

12、事件修饰符和按键修饰符有哪些

事件修饰符
	.prevent  阻止事件默认行为
    .stop     阻止事件冒泡
    .capture  设置事件捕获机制
    .self     只有点击元素自身才能触发事件
    .once     事件只触发一次
 按键修饰符
    .tab
    .enter
    .esc
    .space
    .delete(捕获"删除""回退")
    .up
    .down
    .left
    .right

13、v-model修饰符有哪些

.trim   去除首尾空格
.lazy   只在输入框失去焦点或按回车键时更新内容不是实时更新
.number 将数据转换成number类型(原本是字符串类型)

14、v-model的原理是什么

1v-model主要提供了两个功能view层输入值影响data的属性值属性值发生改变会更新层的数值变化.
2v-model指令的实现
	3.1 v-bind:绑定响应式数据
	3.2 触发input事件并传递数据 (核心和重点)
3其底层原理就是(双向数据绑定原理)
	3.1 一方面modal层通过defineProperty来劫持每个属性一旦监听到变化通过相关的页面元素更新
    3.2 另一方面通过编译模板文件为控件的v-model绑定input事件从而页面输入能实时更新相关data属性值

15、v-for中为什么要加key

作用
      1.key的作用主要是为了高效的更新虚拟DOM提高渲染性能
      2.key属性可以避免数据混乱的情况出现
原理
      1.vue实现了一套虚拟DOM并希望"就地更新"节点
      2.当数据发生变化时会使用Diff算法比较新旧虚拟DOM
      3.使用key给每个节点做一个唯一标识在进行Diff算法的时候就会比较key值相同的节点提高性能

16、v-on可以监听多个方法吗

可以
例如
<input type="text" v-on="{ input:onInput,focus:onFocus }">

17、什么是vue的计算属性?

通过计算得来的属性,就是计算属性。

18、watch、methods、computed的区别?

计算属性computed:
1、支持缓存,只有依赖数据发生改变,才会重新进行计算
2、不支持异步,当computed内有异步操作时无效,无法监听数据的变化
3、如果computed需要对数据修改,需要写get和set两个方法,当数据变化时,调用set方法。
4、computed擅长处理的场景:一个结果受多个数据影响,例如购物车计算总价

侦听属性watch:
1、不支持缓存,数据变,直接会触发相应的操作;
2、watch支持异步;可以监听ajax响应结果的变化;
3、支持 immediate和 deep 配置
5、watch擅长处理的场景:一个数据改变影响多个结果

方法methods:
1、不会自动执行,需要调用才会执行
2、结果不会缓存,每调用一次,就会执行一次

19、怎么在watch监听开始之后立即被调用?

在选项参数中指定 immediate: true

watch: {
  xxx: {
    handler () {},
    immediate: true
  }
}

20、watch的属性用箭头函数定义结果会怎么样

不应该使用箭头函数来定义 watch :
例如
    watch: {
      a: () => {  //  这里不应该用箭头函数
        console.log(this);
        this.sum = this.a + this.b;
      }
    })
理由是箭头函数绑定了父级作用域的上下文所以 this 将不会按照期望指向 Vue 实例
this.a 将是 undefined

注意methods里面定义的方法也不要用箭头函数

21、computed、data、methods、props可以同名吗?

不能同名,因为不管是 computed 属性名还是 data 数据名还是 props 数据名,还是methods方法,都 会被挂载在 vm 实例上,因此这几个都不能同名。

22、vue组件中的data为什么必须是函数?

1、每个组件都是 Vue 的实例。
2、组件共享 data 属性,当 data 的值是同一个引用类型的值时,改变其中一个会影响其他。
3、组件中的 data 写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的 data,类似于给每个组件实例创建一个私有 的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式, 就使得所有组件实例共用了一份 data,就会造成一个变了全都会变的结果。

四、组件

23、你知道style加scoped属性的用途和原理吗

用途防止全局同名CSS污染
原理在标签加上v-data-something属性再在选择器时加上对应[v-data-something]即CSS带属性选择器以此完成类似作用域的选择方式.
	scoped会在元素上添加唯一的属性data-v-x形式),css编译后也会加上属性选择器从而达到限制作用域的目的

24、$nextTick是什么?原理是什么

背景
	1简单来说Vue 在修改数据后视图不会立刻更新而是等同一事件循环中的所有数据变化完成之后再统一进行视图更新
    
定义
	2在下次 DOM 更新循环结束之后执行延迟回调在修改数据之后立即使用这个方法获取更新后的 DOMnextTick()是将回调函数延迟在下一次dom更新数据后调用简单的理解是当数据更新了在dom中渲染后自动执行该函数
    
原理
	3vue用异步队列的方式来控制DOM更新和nextTick回调先后执行
	简单来说nextTick是做了promise加上setTimeout的封装,利用事件换行机制来确保当nextTick出现时都是在我们所有操作DOM更新之后的

场景
	4.1 点击获取元素宽度
    4.2 使用swiper插件通过 ajax 请求图片后的滑动问题
    4.3 点击按钮显示原本以 v-show = false 隐藏起来的输入框并获取焦点

25、vue组件间是如何进行传值的?

1)父组件向子组件传递数据 。

2)子组件向父组件传递数据 。

3)非父子组件之间传递数据

4)另外,也可以使用 vuex 进行组件间的数据共享
代码参考:

1父传子
    通过props传递
    父组件 <child :list = 'list' />
    子组件: props['list'],接收数据,接受之后使用和data中定义数据使用方式一样

2子传父
	在父组件中给子组件绑定一个自定义的事件子组件通过$emit()触发该事件并传值
    父组件 <child @receive = 'getData' />
            getData(value){value就是接收的值}
    子组件: this.$emit('receive',value)

3兄弟组件传值
	通过中央通信 let bus = new Vue()
    A组件methods :{ 
    	    		sendData(){
                bus.$emit('getData',value)
              }
           } 发送
    B组件created(){
        		bus.$on(getData,(value)=>{value就是接收的数据})
    			} 进行数据接收

26、谈谈你对slot的了解

slot就是插槽,主要是封装组件的时候,用它来占位。
然后其他组件使用这个封装的组件的时候,给 slot 提供页面结构。

1 默认插槽  在子组件中写入slotslot所在的位置就是父组件要显示的内容
2 具名插槽  在子组件中定义了多个slot标签则需要通过name属性来区分这些插槽加入了name属性的插槽就是具名插槽
    			 在父组件中使用template并写入对应的slot名字来指定该内容在子组件中现实的位置
3 作用域插槽  在子组件的slot标签上绑定需要的值<slot :data="user"></slot>
    	        在父组件上使用 v-slot:插槽名="user"    #插槽名="user" 来接收子组件传过来的值

27、请说下封装vue组件的过程。

封装组件就是为了复用,可以提升整个项目的开发效率。
封装的大致逻辑:
1)根据需求,把可以复用的结构,样式以及功能,单独抽离成一个组件,主要是为了实现复用嘛。
2)封装的组件,一般会放到 components 文件夹里面,并且在main.js中注册,方便在其他组件中调用。
3)传递数据的话,就是父传子或子传父。
4)需要传递页面结构的话,就用插槽。
5)还有,vue3中,如果需要 父组件主动调用子组件的方法 可以在 methods 选项中开放方法

28、vue是如何获取DOM

1先给标签设置一个ref值再通过this.$refs.domName获取这个操作要在mounted阶段进行
2例如
<template>
	<div ref="test"></div>
</template>
mounted(){
   const dom = this.$refs.test 
}

29、vue该如何实现组件缓存?

使用 包裹动态组件,即可实现动态组件的缓存。
可以通过include 属性设置哪些组件需要被缓存,也可以通过exclude设置哪些组件不需要被缓存。

30、谈谈你对 keep-alive 的了解

1keep-alive  Vue 内置的一个组件可以使被包含的组件保留状态避免重新渲染
2一般结合路由和动态组件一起使用用于缓存组件
3对应两个钩子函数 activated  deactivated 当组件被激活时触发钩子函数 activated当组件被移除时触发钩子函数 deactivated
4提供 include  exclude 属性两者都支持字符串或正则表达式 include 表示只有名称匹配的组件会被缓存exclude 表示任何名称匹配的组件都不会被缓存 其中 exclude 的优先级比 include 
例如
<keep-alive include="a">
 <component>
  <!-- name  a 的组件将被缓存 -->
 </component>
</keep-alive>

<keep-alive exclude="a">
 <component>
  <!-- 除了 name  a 的组件都将被缓存 -->
 </component>
</keep-alive>

31、vue中动态组件如何使用

1在某个中使用 is 特性来切换不同的组件
	<component :is="TabComponent"></component>   TabComponent:已注册组件的名

32、vue怎么实现强制刷新组件

第一.使用this.$forceUpdate强制重新渲染
    <template>
    <button @click="reload()">刷新当前组件</button>
    </template>
    <script>
    export default {
        name: 'comp',
        methods: {
            reload() {
                this.$forceUpdate()
            }
        }
    }
    </script>

第二.使用v-if指令
<template>
    <comp v-if="update"></comp>
    <button @click="reload()">刷新comp组件</button>
</template>
<script>
import comp from '@/views/comp.vue'
export default {
    name: 'parentComp',
    data() {
        return {
            update: true
        }
    },
    methods: {
        reload() {
            // 移除组件
            this.update = false
            // 在组件移除后,重新渲染组件
            // this.$nextTick可实现在DOM 状态更新后,执行传入的方法。
            this.$nextTick(() => {
                this.update = true
            })
        }
    }
}
</script>

33、如何在子组件中访问父组件的实例

Vue中子组件调用父组件的方法这里有三种方法提供参考
    1直接在子组件中通过this.$parent.event来调用父组件的方法
    2在子组件里用$emit向父组件触发一个事件父组件监听这个事件
    3父组件把方法传入子组件中在子组件里直接调用这个方法

五、Vuex

34、Vuex 是什么?有哪几种属性?

  1Vuex 是专为Vue设计的状态管理工具采用集中式储存管理 Vue 中所有组件的状态
  2属性
  1state属性基本数据
  2getters属性 state 中派生出的数据
  3mutation属性更新 store 中数据的唯一途径其接收一个以 state 为第一参数的回调函数
  4action 属性提交 mutation 以更改 state其中可以包含异步操作数据请求
  5module 属性用于将 store分割成不同的模块

35、vuex的出现解决了什么问题?

主要解决了以下两个问题:
1, 大面积的数据共享,解决了多个组件共用一份数据的问题。
2, 多个组件都需要修改同一份数据,变得非常容易维护。

36、vuex的mutation和action之间的区别是什么?

Mutation:专注于修改 State,理论上是修改 State 的唯一途径,里面只能放同步代码
Action:放业务代码、异步请求,不能直接操作 State,需要调用 mutation 操作State。

37、刷新浏览器后,vuex的数据是否存在?如何解决?

刷新后,vuex的数据肯定不存在了,因为 store 里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被重新初始化。
可以通过插件(vuex-alongvuex-persist)将store中的数据存储到localStorage里面。

六、概念、原理

38、怎么理解vue中的虚拟DOM

原理	
	 JS 对象模拟真实 DOM 对真实 DOM 进行抽象
diff 算法  比较两棵虚拟 DOM 树的差异
pach 算法  将两个虚拟 DOM 对象的差异应用到真正的 DOM 

好处
	1性能优化
    2无需手动操作DOM
    3可以跨平台服务端渲染等

39、说说你对SPA单页面的理解。

SPA,就是单页 Web 应用 ,也就是说项目只有一个页面,所有的操作都在一个页面中完成。
SPA 的优缺点:
1)优点:

  1. 无刷新界面,给用户体验原生的应用感觉
  2. 节省原生开发成本,提高发布效率(无需每次安装更新包)。
  3. 容易借助其他知名平台营销和推广
  4. 符合 web2.0 的趋势

2)缺点:
1、性能和用原生JS开发的项目有一定差距
2、各个浏览器的版本兼容性不一样
3、业务随着代码量增加而增加,不利于首屏优化,不利于搜索引擎抓取
4、某些平台对 hash 有偏见

40、怎么理解vue的单向数据流?

数据从父级组件传递给子组件,只能单向绑定。

41、怎么理解mvvm这种设计模式

ModelViewViewModel MVVM 是一个软件架构设计模式是一种简化用户界面的事件驱动编程方式
MVVM
    M Model 模型 指的是数据层
    V View  视图 指的是用户页面
    VM ViewModel 视图模型
    视图模型(VM)是MVVM模式的核心它是连接view和model的桥梁
      - 当model的属性改变时VM会监听数据的变化并更新view
      - 反之当view变化后VM也会将数据更新到model层。(我们称之为数据的双向绑定

42、mvvm 和 mvc 区别是什么?哪些场景适合?

MVC 和 MVVM 二者都是设计思想。主要区别是 MVC 中的 C(Controller) 演变成 MVVM 中的 VM(viewModel)

所以,数据操作比较多的场景,需要大量操作 DOM 元素时,采用 MVVM 的开发方式,会更加便捷,让开发者更多的精力放在数据的变化上,避免繁琐的 DOM 操作。

43、组件化和模块化的区别

1组件相当于库把一些能在项目里或者不同类型项目中可复用的代码进行工具性的封装
2模块相应于业务逻辑模块把同一类型项目里的功能逻辑进行进行需求性的封装

44、你认为vue的核心是什么

组件化
双向数据绑定

45、说说vue的优缺点

优点
    1.中文文档方便学习
    2. 组件化开发可以复用结构
    3. 双向数据绑定
    4. 单页面应用配合路由切换路由时页面局部刷新加快访问速度和用户体验
    5. 有很多第三方的 UI 组件库比如 elementvant等等开发方便
缺点
    1.不支持IE8及以下浏览器
    2.吃内存每个组件都会实例化一个Vue实例实例的属性和方法很多
    3.定义在data里面的对象实例化时都会递归的遍历转成响应式数据然而有的响应式数据我们并不会用到造成性能上的浪费

46、vue响应式的原理

1原理
	Vue 的响应式原理是核心是通过 ES5  Object.defindeProperty 进行数据劫持然后利用 get  set 方法进行获取和设置data 中声明的属性都被添加到了get和set中当读取 data 中的数据时自动调用 get 方法当修改 data 中的数据时自动调用 set 方法检测到数据的变化会通知观察者 Wacher观察者 Wacher自动触发重新render 当前组件子组件不会重新渲染,生成新的虚拟 DOM Vue 框架会遍历并对比新虚拟 DOM 树和旧虚拟 DOM 树中每个节点的差别并记录下来最后加载操作将所有记录的不同点局部修改到真实 DOM 树上

2底层代码实现
	   let data = {
        name: "lis",
        age: 20,
        sex: ""
    }
//  vue2.0实现  使用Object.defineProperty进行数据劫持
    for(let key in data){
        let temp = data[key]
        Object.defineProperty(data, data[key], {
            get(){
                return temp
            },
            set(value){
                temp = value
            }
        })
    }
// vue3.0实现 使用Proxy 进行数据的代理
    let newData = new Proxy(data, {
        get(target, key){
            return target[key]
        },
        set(target, key, value){
            target[key] = value
        }
    })

47、vue2.0和vue3.0响应式的区别

1Object.defineProperty 
  1) 用于监听对象的数据变化
  2) 无法监听数组变化(下标长度)
  3) 只能劫持对象的自身属性动态添加的劫持不到
2Proxy
  1) proxy返回的是一个新对象 可以通过操作返回的新的对象达到目的
  2可以监听到数组变化也可以监听到动态添加的数据

48、SSR了解吗

1SSR也就是服务端渲染也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成然后再把html直接返回给客户端
2SSR有着更好的SEO并且首屏加载速度更快等优点不过它也有一些缺点比如我们的开发条件会受到限制服务器端渲染只支持beforeCreate和created两个钩子当我们需要一些外部扩展库时需要特殊处理服务端渲染应用程序也需要处于Node.js的运行环境还有就是服务器的压力比较大

49、你都做过哪些Vue的性能优化

1v-if和v-for不能连用
2页面采用keep-alive缓存组件
3合理使用v-if和v-show
4key保证唯一
5使用路由懒加载异步组件组件封装
6防抖节流
7第三方模块按需导入
8图片懒加载
9精灵图的使用
10代码压缩

50、怎么解决vue打包后静态资源图片失效的问题

在vue-cli 需要在根目录下建一个vue.config.js 在里面配置publicPath即可
默认值为/更改为./就好了