首页前端开发VUE高频Vue面试题,建议收藏便于经常翻看1

高频Vue面试题,建议收藏便于经常翻看1

时间2023-04-23 08:36:01发布访客分类VUE浏览544
导读:文章目录一.VUE基础内容:1.vue的响应式原理:vue2响应式原理vue3响应式原理2.MVM和MVVM的区别:MVCMVC 的思想:一句话描述就是 Controller 负责将 Model 的数据用 View 显示出来,换句话说就是在...

文章目录

  • 一.VUE基础内容:
    • 1.vue的响应式原理:
        • vue2响应式原理
        • vue3响应式原理
    • 2.MVM和MVVM的区别:
      • MVC
    • MVC 的思想:一句话描述就是 Controller 负责将 Model 的数据用 View 显示出来,换句话说就是在 Controller 里面把 Model 的数据赋值给 View。
  • MVVM
    • MVVM 与MVC 最大的区别就是:它实现了 View 和 Model 的自动同步,也就是当 Model 的属性改变时,我们不用再自己手动操作 Dom 元素,来改变 View的显示,而是改变属性后该属性对应 View 层显示会自动改变(对应Vue数据驱动的思想)
  • 整体看来,MVVM 比 MVC 精简很多,不仅简化了业务与界面的依赖,还解决了数据频繁更新的问题,不用再用选择器操作 DOM 元素。因为在 MVVM 中,View 不知道 Model 的存在,Model 和 ViewModel 也观察不到 View,这种低耦合模式提高代码的可重用性
      • 那么问题来了 为什么官方要说 Vue 没有完全遵循 MVVM 思想呢?
  • 3.说一下vue的生命周期:
    • vue2
    • vue3生命周期的变化
    • 一般在那个生命周期请求异步数据
  • 4.为什么 data 是一个函数:
  • 5.v-if、v-show、v-html的原理以及区别
    • 原理:
    • 区别:
  • 6.v-for的扩展
  • 7.v-model原理
      • v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
  • 8.计算属性computed 和watch 的区别是什么?
      • Computed:
      • Watch:
  • 9.常见组件传值
      • 父组件 → 子组件
      • 子组件 → 父组件
      • ref / refs
      • eventBus
  • 10.vue-router 路由钩子函数是什么? 执行顺序是什么?
  • 11.谈一下对 vuex 的个人理解
  • 12.Vue.mixin 的使用场景和原理
  • 13.nextTick 使用场景和原理
    • 14.keep-alive 使用场景和原理
    • 15.Vue.set 方法原理
  • 后续会继续补充!!!

一.VUE基础内容:

1.vue的响应式原理:

vue2响应式原理

整体思路是数据劫持+观察者模式;

当一个Vue实例创建时,Vue会遍历data中的属性,用 Object.defineProperty(vue3.0使用proxy )将它们转为 getter/setter,并且在内部追踪相关依赖,

在属性被访问和修改时通知变化。每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。

相关代码如下:

class Observer {

  // 观测值
  constructor(value) {
    
    this.walk(value);

  }

  walk(data) {
    
    // 对象上的所有属性依次进行观测
    let keys = Object.keys(data);
    
    for (let i = 0;
     i  keys.length;
 i++) {
    
      let key = keys[i];
    
      let value = data[key];
    
      defineReactive(data, key, value);

    }

  }

}

// Object.defineProperty数据劫持核心 兼容性在ie9以及以上
function defineReactive(data, key, value) {
    
  observe(value);
     // 递归关键
  // --如果value还是一个对象会继续走一遍odefineReactive 层层遍历一直到value不是对象才停止
  //   思考?如果Vue数据嵌套层级过深 >
    >
性能会受影响
  Object.defineProperty(data, key, {

    get() {
    
      console.log("获取值");
    

      //需要做依赖收集过程 这里代码没写出来
      return value;

    }
,
    set(newValue) {
    
      if (newValue === value) return;
    
      console.log("设置值");
    
      //需要做派发更新过程 这里代码没写出来
      value = newValue;

    }
,
  }
    );

}

export function observe(value) {

  // 如果传过来的是对象或者数组 进行属性劫持
  if (
    Object.prototype.toString.call(value) === "[object Object]" ||
    Array.isArray(value)
  ) {
    
    return new Observer(value);

  }

}
    

vue3响应式原理

Vue3改用 Proxy 替代 Object.defineProperty。因为 Proxy 可以直接监听对象和数组的变化,并且有多达 13 种拦截方法。

import {
 mutableHandlers }
     from "./baseHandlers";
 // 代理相关逻辑
import {
 isObject }
     from "./util";
 // 工具方法

export function reactive(target) {
    
  // 根据不同参数创建不同响应式对象
  return createReactiveObject(target, mutableHandlers);

}

function createReactiveObject(target, baseHandler) {

  if (!isObject(target)) {
    
    return target;

  }
    
  const observed = new Proxy(target, baseHandler);
    
  return observed;

}
    

const get = createGetter();
    
const set = createSetter();


function createGetter() {

  return function get(target, key, receiver) {
    
    // 对获取的值进行放射
    const res = Reflect.get(target, key, receiver);
    
    console.log("属性获取", key);

    if (isObject(res)) {
    
      // 如果获取的值是对象类型,则返回当前对象的代理对象
      return reactive(res);

    }
    
    return res;

  }
    ;

}

function createSetter() {

  return function set(target, key, value, receiver) {
    
    const oldValue = target[key];
    
    const hadKey = hasOwn(target, key);
    
    const result = Reflect.set(target, key, value, receiver);

    if (!hadKey) {
    
      console.log("属性新增", key, value);

    }
 else if (hasChanged(value, oldValue)) {
    
      console.log("属性值被修改", key, value);

    }
    
    return result;

  }
    ;

}

export const mutableHandlers = {

  get, // 当获取属性时调用此方法
  set, // 当修改属性时调用此方法
}
    ;
    

2.MVM和MVVM的区别:

MVC

MVC 全名是 Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范

  • Model(模型):是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据
  • View(视图):是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的
  • Controller(控制器):是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据

MVC 的思想:一句话描述就是 Controller 负责将 Model 的数据用 View 显示出来,换句话说就是在 Controller 里面把 Model 的数据赋值给 View。

MVVM

MVVM 新增了 VM 类

  • ViewModel 层:做了两件事达到了数据的双向绑定 一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听

MVVM 与 MVC 最大的区别就是:它实现了 View 和 Model 的自动同步,也就是当 Model 的属性改变时,我们不用再自己手动操作 Dom 元素,来改变 View 的显示,而是改变属性后该属性对应 View 层显示会自动改变(对应Vue数据驱动的思想)

整体看来,MVVM 比 MVC 精简很多,不仅简化了业务与界面的依赖,还解决了数据频繁更新的问题,不用再用选择器操作 DOM 元素。因为在 MVVM 中,View 不知道 Model 的存在,Model 和 ViewModel 也观察不到 View,这种低耦合模式提高代码的可重用性

注意:Vue 并没有完全遵循 MVVM 的思想 这一点官网自己也有说明

那么问题来了 为什么官方要说 Vue 没有完全遵循 MVVM 思想呢?

严格的 MVVM 要求 View 不能和 Model 直接通信,而 Vue 提供了 $refs 这个属性,让 Model 可以直接操作 View,违反了这一规定,所以说 Vue 没有完全遵循 MVVM。

3.说一下vue的生命周期:

vue2

「beforeCreate」 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问

「created」 实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。这里没有el,如果非要想与Dom进行交互,可以通过==vm.nextTick ==来访问 Dom

「beforeMount」 在挂载开始之前被调用:相关的 render 函数首次被调用。

「mounted」 在挂载完成后发生,在当前阶段,真实的 Dom 挂载完毕,数据完成双向绑定,可以访问到 Dom 节点

「beforeUpdate」 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁(patch)之前。可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程

「updated」 发生在更新完成之后,当前阶段组件 Dom 已完成更新。要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新,该钩子在服务器端渲染期间不被调用。

「beforeDestroy」 实例销毁之前调用。在这一步,实例仍然完全可用。我们可以在这时进行善后收尾工作,比如清除计时器。

「destroyed」 Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用

「activated」 keep-alive 专属,组件被激活时调用

「deactivated」 keep-alive 专属,组件被销毁时调用

vue3生命周期的变化

setup取代beforeCreate和created

vue3的组合式api中,setup中的函数执行相当于在选项api中的beforeCreate和created中执行


组合式api的生命周期需引入使用

除了beforeCreate和created外,其他生命周期的使用都需要提前引入(轻量化)


可使用的生命周期

除了beforeCreate和created被setup取代之外,选项式api和组合式api的映射如下:


beforeMount -> onBeforeMount,在挂载前被调用


mounted -> onMounted,挂载完成后调用


beforeUpdate -> onBeforeUpdate,数据更新时调用,发生在虚拟 DOM 打补丁之前。此时内存中的 数据已经被修改,但还没有更新到页面上


updated -> onUpdated,数据更新后调用,此时内存数据已经修改,页面数据也已经更新


beforeUnmount -> onBeforeUnmount,组件卸载前调用


unmounted -> onUnmounted,卸载组件实例后调用。


errorCaptured -> onErrorCaptured,每当事件处理程序或生命周期钩子抛出错误时调用


renderTracked -> onRenderTracked,状态跟踪,vue3新引入的钩子函数,只有在开发环境有用,用于跟踪所有响应式变量和方法,一旦页面有update,就会跟踪他们并返回一个event对象


renderTriggered -> onRenderTriggered,状态触发,同样是vue3新引入的钩子函数,只有在开发环境有效,与onRenderTracked的效果类似,但不会跟踪所有的响应式变量方法,只会定点追踪发生改变的数据,同样返回一个event对象


activated -> onActivated,与keep-alive一起使用,当keep-alive包裹的组件激活时调用


deactivated -> onDeactivated,与keep-alive一起使用,当keep-alive包裹的组件停用时调用

  1. 一般在那个生命周期请求异步数据

我们可以在钩子函数created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:能更快获取到服务端数据,减少页面加载时间,用户体验更好;SSR不支持 beforeMount 、mounted 钩子函数,放在 created 中有助于一致性。

4.为什么 data 是一个函数:

组件中的 data 写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的 data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份 data,就会造成一个变了全都会变的结果

5.v-if、v-show、v-html的原理以及区别

原理:

v-if会调用addIfCondition方法,生成vnode的时候会忽略对应节点,render的时候就不会渲染;

v-show会生成vnode,render的时候也会渲染成真实节点,只是在render过程中会在节点的属性中修改show属性值,也就是常说的display;

v-html会先移除节点下的所有节点,调用html方法,通过addProp添加innerHTML属性,归根结底还是设置innerHTML为v-html的值。

区别:

相同点:v-show 和v-if都是true的时候显示,false的时候隐藏

不同点1:原理不同

v-show:一定会渲染,只是修改display属性

v-if:根据条件渲染

不同点2:应用场景不同

频繁切换用v-show,不频繁切换用v-if

v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建,操作的实际上是dom元素的创建或销毁。


v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换 它操作的是display:none/block属性。


一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好


声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

JavaScript前端开发API数据库UED

若转载请注明出处: 高频Vue面试题,建议收藏便于经常翻看1
本文地址: https://pptw.com/jishu/6142.html
Vue2.js迁移到Vue3.js的API变化 美国大流量服务器有什么特点

游客 回复需填写必要信息