Vue全家桶

89 阅读2分钟

Vue中的key到底有什么⽤

key是为Vue中的vnode标记的唯⼀id,通过这个key,我们的diff操作可以更准确、更快速。diff算法的过程中,先会进⾏新旧节点的⾸尾交叉对⽐,当⽆法匹配的时候,会⽤新节点的key与旧节点进⾏⽐对,然后找出差异

你对MVVM的理解

  • Model 代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑
  • View 代表UI 组件,它负责将数据模型转化成UI 展现出来
  • ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View和 Model的对象,连接Model和View的桥梁

响应式数据的理解

defineReactive函数里面使用了Object.defineProperty

function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function () {
      return val;
    },
    set: function (newVal) {
      //判断新值与旧值是否相等
      //判断的后半段是为了验证新值与旧值都为NaN的情况  NaN不等于自身
      if (newVal === val || (newVal !== newVal && value !== value)) {
        return;
      }
      val = newVal;
    }
  });
}

Dep构造函数负责依赖收集(subs数组)和派发更新(notify方法)

class Dep {
  constructor() {
    //订阅的信息
    this.subs = [];
  }

  addSub(sub) {
    this.subs.push(sub);
  }

  removeSub(sub) {
    remove(this.subs, sub);
  }

  //此方法的作用等同于 this.subs.push(Watcher);
  depend() {
    if (Dep.target) {
      Dep.target.addDep(this);
    }
  }
  //这个方法就是发布通知了 告诉你 有改变啦
  notify() {
    const subs = this.subs.slice()
    for (let i = 0, l = subs.length; i < l; i++) {
      subs[i].update();
    }
  }
}
Dep.target = null;

如何实现监听数组变化的

  • Vue 中解决这个问题的方法,是将数组的常用方法进行重写,通过包装之后的数组方法就能够去在调用的时候被监听到
// 让 arrExtend 先继承 Array 本身的所有属性
const arrExtend = Object.create(Array.prototype)
const arrMethods = [
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse'
]
/**
 * arrExtend 作为一个拦截对象, 对其中的方法进行重写
 */
arrMethods.forEach(method => {
  const oldMethod = Array.prototype[method]
  const newMethod = function (...args) {
    oldMethod.apply(this, args)
    console.log(`${method}方法被执行了`)
  }
  arrExtend[method] = newMethod
})

export default {
  arrExtend
}

模板编译原理

  • 通过parseHTML方法生成AST树
  • 再通过optimize方法进行优化
  • 最后codegen将优化后的AST树转换为可执行的代码

父子组件生命周期的执行顺序

  • 编译时,放到mergeOption数组
父组件子组件
父beforeCreate
父created
父beforeMounted
子beforeCreate
子created
子beforeMounted
子mounted
父mounted

mixin 和 mixins 区别

  • mixin 用于全局混入,会影响到每个组件实例,通常插件都是这样做初始化的
  • mixins 应该是我们最常使用的扩展组件的方式

vue中的nextTick

  • 在下次dom更新结束之后执行异步回调,可用于获取更新后的dom状态
  • 先判断能否使用setImmediate,不能的话使用MessageChannel,最后使用setTimeout

DOM Diff

  • 深度优先遍历 + 双指针

为什么虚拟dom会提高性能

  • 虚拟dom相当于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的dom操作,从而提高性能

vue和react的区别

  • react
    生命周期
    setState是异步的
    HOC(高阶组件)
  • vue双向数据绑定,而react是setState
  • jsx,对于初学者,react上手慢

vue3和vue2的区别

  • vue2和vue3双向数据绑定原理发生了改变
  • 新加入了 TypeScript 以及 PWA 的支持

v-for优先于v-if

vuex

  • state: 状态中心
  • getters: 获取状态
  • mutations: 更改状态
  • actions: 异步更改状态
    当组件进行数据修改的时候我们需要调用dispatch来触发actions里面的方法。actions里面的每个方法中都会有一个commit方法,当方法执行的时候会通过commit来触发mutations里面的方法进行数据的修改。mutations里面的每个函数都会有一个state参数,这样就可以在mutations里面进行state的数据修改,当数据修改完毕后,会传导给页面。页面的数据也会发生改变
  • modules: 将state分成多个modules,便于管理

前端路由(vue-router)

  • 原理
    前端路由实现起来其实很简单,hash路由本质就是监听 URL 的变化,然后匹配路由规则,而history是由于HTML5 history新增了两个API:history.pushState和history.replaceState

  • 模式
    hash
    history
    通过back(), forward(), go()等方法,我们可以读取浏览器历史记录栈的信息,进行各种跳转操作。

  • 使用

    this.$router.push()
    <router-link to=""></router-link>
    
  • routeroute和router的区别 route是“路由信息对象”,包括pathparamshashqueryfullPathmatchedname等路由信息参数而route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数 而router是“路由实例”对象包括了路由的跳转方法,钩子函数等

  • 导航守卫
    全局前置守卫 router.beforeEach((to,from,next)=>{})
    全局后置钩子 router.afterEach((to,from)=>{})
    组件内的守卫 beforeRouteEnter:(to,from,next)=>{}
    路由独享的守卫 beforeEnter:(to,from,next)=>{}

keep-alive

  • keep-alive可以实现组件缓存,当组件切换时不会对当前组件进行卸载
  • 常用的两个属性include/exclude,允许组件有条件的进行缓存
  • 两个生命周期activated/deactivated,用来得知当前组件是否处于活跃状态
  • keep-alive的中还运用了LRU(Least Recently Used)最近最少使用算法

内置组件

  • component
  • transition
  • transition-group
  • keep-alive
  • slot

插槽(slot)

  • 普通插槽 子组件渲染
  • 作用域插槽 父组件渲染

如何理解自定义指令

  • 生成AST语法树
  • genDirective生成指令代码放在数组里
  • 渲染时,bind方法调用

修饰符有哪些

  • capture/once/passive/stop/self/prevent

v-if和v-show的区别

  • 当条件不成立时,v-if不会渲染DOM元素,v-show操作的是样式(display),切换当前DOM的显示和隐藏

组件通信

  1. 父子组件通信
    父->子props,子->父 onon、emit
    获取父子组件实例 parentparent、children
    Ref 获取实例的方式调用组件的属性或者方法
  2. 兄弟组件通信
    Event Bus 实现跨组件通信 Vue.prototype.$bus = new Vue
    Vuex
  3. 跨多层级组件通信
    Vuex
    attrsattrs、listeners
    provide、inject