Vue原理:数据初始化流程

858 阅读2分钟

这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战

Vue2中的响应式原理是开发者们津津乐道的一个话题,也是面试的一道高频题目,在开始之前需要先了解一下Vue初始化的一个大致流程

Vue初始化

首先看一下我们在使用Vue时一个最基本的使用

new Vue({
  el: '#app',
  data() {
    return {
      name: 'nordon',
      age: 12
    }
  },
  computed() {},
  methods: {
  },
})

当我们如上使用Vue时,其便会进行一个初始化的过程,接下来便一起看看Vue是如何处理的

在上篇文章中已经介绍了使用Rolleup搭建开发环境,创建了src/index.js文件作为入口文件,那么当使用new Vue时会传递非常多的选项,如果都放在index.js中处理明显是不合适的,因为它作为入口文件主要的作用就是整合,将不同的功能抽取到对应的文件中,因此需要单独创建一个init.js处理初始化的功能

此时index.js内容

import { initMixin } from "./init";
/**
 * Vue 的一个声明
 */
function Vue(options) {
  this._init(options);
}

initMixin(Vue)

export default Vue;

后续会存在生命周期、渲染、全局API等很多初始化过程,都会通过拆分代码到不同的文件中进行维护

init.js内容

/**
 * 初始化混合操作
 *  主要是在Vue的原型上增加一个init函数
 */
export function initMixin(Vue) {
  /**
   * Vue 初始化操作
   */
  Vue.prototype._init = function (options) {
  };
}

数据初始化

vue的数据来源非常多,可以通过data、props、methods、computed、watch等,需要根据不同的选项类型进行对应的初始化处理,这个逻辑也是非常多,需要将其拆分到state.js

此时init.js

Vue.prototype._init = function (options) {
  // this.$options 指代的就是开发者传递的选项
  const vm = this;
  vm.$options = options;

  // 初始化状态
  initState(vm);
};

需要注意:Vue中会将用户传递的选项全部挂在到实例vm$options上,后续各个模块之间的流转中只需要传递vm即可,因为vm.$options可以获取到全部的传递选项信息

创建state.js并编写代码

export function initState(vm) {
  const ops = vm.$options; // 获取用户全部选项

  if (ops.props) {
    // 传递了属性
    initProps(vm);
  }

  if (ops.methods) {
    // 传递了方法
    initMethod(vm);
  }

  if (ops.data) {
    //传递了数据
    initData(vm);
  }

  if (ops.computed) {
    // 传递了计算属性
    initComputed(vm);
  }

  if (ops.watch) {
    //传递了监听
    initWatch(vm);
  }
}

function initProps(vm) {}
function initMethod(vm) {}
function initData(vm) {}
function initComputed(vm) {}
function initWatch(vm) {}

上述代码将不同的选项逻辑拆分到不同的函数中,每个函数保持职责单一原则

接下来便是处理数据初始化

在初始化传入data可以是对象,也可以是一个函数,首选需要对data进行处理,保证最终得到的都是一个对象

let data = vm.$options.data;

// 对data进行处理
data = vm._data = typeof data === "function" ? data.call(vm) : data;

data赋值给vm._data方便开发者可以直接访问到传递的data数据