Vue 面试面经总结

Vue 面试面经总结

一、vue 组件通信方式?

  • Vue 的设计理念为单向数据流

1. 父子组件通信

1.1 prop

1.1.1 基本用法
<div id="app">
  <child :content="message"></child>
</div>

let Child = Vue.extend({
  template: `

{{message}}

`
, props:{ content:{ type:String, default:() => {return 'form child'} } } }) new Vue({ el:'#app', data:{ message:'form parent' }, components:{ Child } }) // 结果 // form parent
1.1.2子组件接收形式(props)
  1. 数组形式

    props:['data1','data2',……,'datan']
    
  2. 简单对象形式

    props:{
      data1: Number,
      data1: String,
      data1: Boolean,
      data1: Function,
      data1: Object,
      data1: Array,
      data1: Symbol,
    }
    
  3. 复杂对象形式

    props:{
      // 必传且是字符串
     propC: {
       type: String,
       required: true
     },
     // 数字,有默认值
     propD: {
       type: Number,
       default: 100
     },
     // 数组/对象的默认值应当由一个工厂函数返回
     propE: {
       type: Object,
       default: function () {
         return { message: 'hello' }
       }
     },
     // 自定义验证函数
     propF: {
       validator: function (value) {
         return value > 10
       }
     }
    }
    

2. 子父组件通信

2.1 $emit

<div id="app">
  <my-button @receive="sayHi"></my-button>
</div>

let Child = Vue.extend({
  template: ``,
  data(){
    return {
      msg:'vue.js'
    }
  },
  methods:{
    send(){
      this.$emit('receive',this.msg)
    }
  }
})

new Vue({
  el:'#app',
  components:{
    MyButton
  },
  methods:{
    sayHi(val){
      console.log('Hi,'+val)
    }
  }
})

// 结果
// Hi,vue.js

3. 兄弟组件通信

二、请你说说你知道的vue

1. vue是什么?

1.1 基本介绍

Vue.js(/vjuː/,或简称为Vue)

是一个用于创建用户界面的开源JavaScript 渐进式框架,也是一个创建单页面应用的Web应用框架

同时也是一款流行的JavaScript前端框架,旨在更好的组织与简化Web开发。Vue所关注的核心是MVC模式中的视图层,同时,它也能方便地获取数据更新,并通过组件内部特定的方法实现视图与模型的交互

1.2 主要功能

  • 模板渲染/数据同步
  • 组件和模块化
  • 拓展功能:路由等待

1.3 补充:

1.3.1 渐进式框架

就是框架分层,最核心的是视图层渲染,然后往外是组件机制,在此基础上再加入路由机制,再加入状态管理,最外层是构建工具

优势:根据不同的需求选择不同的层级

代表含义:主张最少

理解:不做除自己职责之外的事

1.3.2 单页面应用

单页Web应用,就是只有一张Web页面的应用。浏览器一开始会加载必需的HTML、CSS和JavaScript,之后所有的操作都在这张页面完成,这一切都由JavaScript来控制。

优点
  1. 良好的交互体验

    用户不需要从新刷新页面,获取数据也是通过Ajax异步获取

  2. 良好的前后端工作分离模式

  3. 减轻服务器压力

    服务器只用出数据就可以,不用管展示逻辑和页面合成

  4. 共用一套后端程序代码

缺点
  1. 首次加载大量资源
  2. 对搜索引擎不友好
  3. 开发难度较高

2. Vue核心特性

2.1 数据驱动(MVVM)

MVVM表示的是 Model-View-ViewModel

  • Model 数据模型,负责数据存储
  • View 视图,负责页面的显示
  • VM 负责业务处理,对数据进行加工,之后交给视图

Vue 面试面经总结_第1张图片

2.2 组件化

2.2.1 什么是组件化

把图形、非图形的各种逻辑抽象为一个统一的概念(组件)来实现开发模式,在vue中每一个 .vue 文件都可以视为一个组件

2.2.2 组件化的优势
  • 降低整个系统的耦合度,在保持接口不变的情况下,我们可以替换不同的组件快速完成需求
  • 调试方便
  • 提高可维护性,对代码优化可获得系统的整体提升

2.3 指令系统

指令是带有 v- 前缀的特殊属性

作用:当表达式的值改变时,将其产生的连带影响响应式地作用于DOM

常用指令:

  • 条件渲染指令 v-if
  • 列表渲染指令 v-for
  • 属性绑定指令 v-bind(:)
  • 事件绑定指令 v-on(@)
  • 双向数据绑定指令 v-model

三、请你说说vue的生命周期?

1. beforeCreate 创建vue实例之前

  • $el为undefined

在new一个vue实例后,只有一些默认的生命周期钩子和默认事件,其他的东西都还没创建。在beforeCreate生命周期执行的时候,data和methods中的数据都还没有初始化。不能在这个阶段使用data中的数据和methods中的方法

2. created 创建实例成功

  • 一般在这里实现数据的异步请求
  • $el为undefined

data 和 methods都已经被初始化好了,如果要调用 methods 中的方法,或者操作 data 中的数据,最早可以在这个阶段中操作

3. beforeMount 挂载前

  • el为object

执行到这个钩子的时候,在内存中已经编译好了模板了,但是还没有挂载到页面中,此时,页面还是旧的

4. mounted 挂载后

执行到这个钩子的时候,就表示Vue实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段。 如果我们想要通过插件操作页面上的DOM节点,最早可以在和这个阶段中进行

5. beforeUpdate 更新前

当执行这个钩子时,页面中的显示的数据还是旧的,data中的数据是更新后的, 页面还没有和最新的数据保持同步

6. updated 更新后

页面显示的数据和data中的数据已经保持同步了,都是最新的

7. beforeDestroy 销毁前

Vue实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于可用状态。还没有真正被销毁

8. destroyed 销毁后

这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于不可用状态。组件已经被销毁了

9. 试题:

9.1 什么是生命周期?

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

9.2 vue生命周期的作用是什么?

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

9.3 vue生命周期总共有几个阶段?

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

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

会触发 下面这几个beforeCreate, created, beforeMount, mounted

9.5 DOM 渲染在 哪个周期中就已经完成?

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

四、vue请求数据放在created好还是mounted里好

建议放在created里
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。

如果在mounted钩子函数中请求数据可能导致页面闪屏问题
其实就是加载时机问题,放在created里会比mounted触发早一点,如果在页面挂载完之前请求完成的话就不会看到闪屏了

五、请你说说vue中$nextTick用法及原理

1. 定义

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

官方理解:Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM

个人理解:nextTick(),是将回调函数延迟在下一次dom更新数据后调用,即数据更新了,在dom渲染完成后调用该函数

2. 基本用法

<div class="app">
  <div ref="msgDiv">{{msg}}</div>
  <div v-if="msg1">{{msg1}}</div>
  <div v-if="msg2">{{msg2}}</div>
  <button @click="changeMsg">点击修改……</button>
</div>

new Vue({
  el: '.app',
  data: {
    msg: 'Hello world.',
    msg1: '',
    msg2: ''
  },
  methods: {
    /*
    * 通过 this.$refs.msgDiv.innerHTML 操作 ref="msgDiv" 指向的DOM
    */
    changeMsg() {
      this.msg = "Hello vue."
      // 调用了 this.$nextTick() 将会在下一次 DOM 更新之后执行(此时,msg已修改为Hello vue.且页面已更新完成)
      this.$nextTick(() => {
        //this.$refs.msgDiv.innerHTML = 'Hello vue.'
        this.msg1 = this.$refs.msgDiv.innerHTML
      })
      // 当点击时Dom还未更新,获取到的msgDiv.innerHTML仍然是未更新前页面上渲染的数据(Hello world.)
      // this.$refs.msgDiv.innerHTML = 'Hello world.'
      this.msg2 = this.$refs.msgDiv.innerHTML
    }
  }
})

/*
* 点击前:
* 		Hello world.
* 		点击修改……
* 
* 点击后:
* 		Hello world.
* 		Hello vue.
* 		Hello world.
* 		点击修改……
*/

3. 应用场景

  1. 在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中

    created()钩子函数执行的时候DOM 其实并未进行任何渲染

  2. 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。

六、vue 中的 data为什么是函数?

1. 问题描述

为什么在vue组件中,我们的data属性必须是一个函数,new Vue()中的data除外,因为new Vue中只有一个data属性

2. 原因

因为我们能抽离出来的组件,肯定是具有复用性的,它在项目中会存在多个实例。如果data属性值是一个对象时,那么它所有的实例都会共享这些数据,这是很麻烦的事情,你不能确保你的所有实例中的属性值都不会重复,无论在哪个组件实例中修改data,都会影响到所有的组件实例

期望:每个组件都能独立维护自己的数据

3. 问题解决

  • 在JavaScript中,函数具有独立作用域快的特点,外部是无法访问其内部的变量
// 声明构造器函数
function Person() {}
Person.prototype.data = {
  // 原型下挂载一对象,并有name属性
  name: 'Hello World!',
};

var p1 = new Person();
var p2 = new Person();
p1.data.name = 'Hello Vue!';
console.log(p1.data.name); // Hello Vue!
console.log(p2.data.name); // Hello Vue!

此时原型下为一个对象,p1,p2均指向同一个实体

原型下的属性相当于公有的

修改一个实例对象下的属性也会造成另一个实例属性跟着改变,这样组件复用的时候,肯定是不行的,那么改成函数呢?

// 声明构造器函数
function Person() {
  this.data = this.data()
}
Person.prototype.data = {
  // 原型下挂载一对象,并有name属性
  name: 'Hello World!',
};

var p1 = new Person();
var p2 = new Person();
p1.data.name = 'Hello Vue!';
console.log(p1.data.name); // Hello Vue!
console.log(p2.data.name); // Hello World!

由此得出:若原型下为一个函数,根据函数具有独立作用域快的特点,完美地达到了每个组件都能独立维护自己的数据

同理,在vue中要想组件能到达复用的效果,data必须是一个函数

七、Vue的computed、watch、methods用法及其区别

1. Computed

1.1 定义

是一个计算属性,类似于过滤器,对绑定到view的数据进行处理

1.2 基本用法

computed:{ 属性名:function(){ return 返回值; } }

  • 在computed中定义的不是方法,而是属性
  • 计算属性在data中不用定义
<div id="app">
  <p>{{ list }}</p>
  <p>{{ sumList }}</p>
</div>

var app = new Vue({
  el: '#app',
  data: {
    list: [9,3,5,7]
  },
  computed: {
    // 计算属性的 getter
    sumList: function () {
      var sum = 0
      for(let i=0;i<=this.list;i++){
        sum = sum + list[i]
      }
      return sum
    }
  }
})
  1. 上述代码中的计算属性为sumList
  2. 计算属性执行的function中涉及到的数据量被称为计算属性的依赖数据
  3. 计算属性:当该属性的依赖数据发生变化时,则该属性会重新进行计算
  4. 计算属性执行的function中renturn的返回值是计算属性计算的最终结果

1.3 getter && setter

计算属性包含两个操作:

  1. getter,获取计算属性的结果,默认的function是获取结果(所以可以省略不写)。用get:function(){}实现。当依赖数据发生变化时会自动执行get函数。

  2. setter,设置计算属性的结果。用set:function(){}实现。当计算属性通过v-model绑定在表单元素上,用户对表单元素的值进行了修改时执行set函数。

    computed:{
      sumList:{
          get:function(){
              return 返回值
          },
          set:function(参数){
              
          }
      }
    }
    
    // ...
    computed: {
      fullName: {
        // getter
        // 回调函数 当需要读取当前属性值是执行,根据相关数据计算并返回当前属性的值
        get: function () {
          return this.firstName + ' ' + this.lastName
        },
        // setter
        // 监视当前属性值的变化,当属性值发生变化时执行,更新相关的属性数据
        // newValue :fullName的最新值
        set: function (newValue) {
          var names = newValue.split(' ')
          this.firstName = names[0]
          this.lastName = names[names.length - 1]
        }
      }
    }
    // ...
    

2. Watch

2.1 定义

watch 是一个观察的动作

2.2 基本用法

  • 当price值变化时,watch监听到并且执行
<div>
      <p>FullName: {{Price}}</p>
      <p>FirstName: <input type="text" v-model="price"></p>
</div>
 
new Vue({
  el: '#root',
  data: {
    price: '2',
    symbolUnit: '¥',
    Price:''
  },
  watch: {
    price(newName, oldName) {
      this.Price = newName + this.symbolUnit;
    }
  } 
})

2.3 handler 方法和 immediate 属性:

  • 当想让值在最初的时候watch就执行,可以使用 handler 方法和 immediate 属性
watch: {
  price: {
    handler(newName, oldName) {
      this.Price = newName + this.symbolUnit;
    },
    // 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法,如果设置了false,那么效果和上边例子一样
    immediate: true
  }
}

2.4 deep属性

  • 深度监听,常用于对象下面属性的改变
<div>
      <p>obj.a: {{obj.a}}</p>
      <p>obj.a: <input type="text" v-model="obj.a"></p>
</div>
 
new Vue({
  el: '#root',
  data: {
    obj: {
      a: 123
    }
  },
  watch: {
    obj: {
      handler(newName, oldName) {
         console.log('obj.a changed');
      },
      immediate: true
    }
  } 
})

当我们在输入框中修改a的值时,发现watch是无效的

默认情况下,handler只监听obj这个属性引起的变化,我们只有给obj赋值的时候它才会监听到,而obj.a的改变无法监听

当需要监听 obj.a 时,需要使用 deep 属性

watch: {
  obj: {
    handler(newName, oldName) {
      console.log('obj.a changed');
    },
    immediate: true,
    deep: true
  }
}

而同时这种方法对性能影响很大,修改obj里面的任何一个方法都会触发这个监听器里的 handler

改进:

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

3. computed 和 watch 的区别

3.1 computed

  1. 是计算值
  2. 具有缓存性,页面重新渲染值不会变化,计算属性会立即返回之前的计算结果,而不必再次执行函数(只有当依赖数据发生改变才会重新计算)
  3. 不支持异步,当computed内有异步操作时无效,无法监听数据的变化

3.2 watch

  1. 是观察的动作

  2. 无缓存性,页面重新渲染时值不变化也会执行(值改变则直接触发)

  3. 支持异步

  4. 监听数据必须是 data 中声明过或者父组件传递过来的props中的数据

4. computed 和 methods 的区别

区别一:

计算属性是基于它的依赖进行实时更新的,方法则是调用才更新

区别二:

计算属性是有缓存的,只要相关依赖没有改变,多次访问计算属性得到的值是之前缓存的计算结果,不会多次执行。操作一个没有依赖项的值也是如此。

任何一个方法都会触发这个监听器里的 handler

改进:

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

3. computed 和 watch 的区别

3.1 computed

  1. 是计算值
  2. 具有缓存性,页面重新渲染值不会变化,计算属性会立即返回之前的计算结果,而不必再次执行函数(只有当依赖数据发生改变才会重新计算)
  3. 不支持异步,当computed内有异步操作时无效,无法监听数据的变化

3.2 watch

  1. 是观察的动作

  2. 无缓存性,页面重新渲染时值不变化也会执行(值改变则直接触发)

  3. 支持异步

  4. 监听数据必须是 data 中声明过或者父组件传递过来的props中的数据

4. computed 和 methods 的区别

区别一:

计算属性是基于它的依赖进行实时更新的,方法则是调用才更新

区别二:

计算属性是有缓存的,只要相关依赖没有改变,多次访问计算属性得到的值是之前缓存的计算结果,不会多次执行。操作一个没有依赖项的值也是如此。

八、vue 页面缓存怎么做?

你可能感兴趣的:(面试面经,vue,vue,面试)