new Vue() 的底层工作原理

当你调用 new Vue() 时,Vue.js 会执行一系列复杂的初始化过程。让我们深入剖析这个看似简单的操作背后发生的事情:

1. 初始化阶段

(1) 内部初始化

function Vue(options) {
  if (!(this instanceof Vue)) {
    warn('Vue is a constructor and should be called with the `new` keyword');
  }
  this._init(options); // 关键初始化入口
}

(2) 合并选项

  • 合并构造函数选项 (Vue.options) 和实例选项 (new Vue 传入的选项)

  • 处理 componentsdirectivesfilters 等

  • 生命周期钩子:合并为数组形式(混入时多个钩子都会执行)

  • data:必须为函数,合并后调用函数返回新对象

  • 自定义合并:可通过 Vue.config.optionMergeStrategies 定制

// 示例:自定义选项合并策略
Vue.config.optionMergeStrategies.customOption = function (parentVal, childVal) {
  return childVal === undefined ? parentVal : childVal;
};

2. 核心初始化流程

(1) 生命周期开始

callHook(vm, 'beforeCreate')

(2) 响应式系统建立

initInjections(vm)   // 处理注入
initState(vm)        // 核心响应式处理
initProvide(vm)      // 处理提供

其中 initState 包含:

if (opts.props) initProps(vm, opts.props)
if (opts.methods) initMethods(vm, opts.methods)
if (opts.data) initData(vm)
if (opts.computed) initComputed(vm, opts.computed)
if (opts.watch) initWatch(vm, opts.watch)

(3) 挂载准备

callHook(vm, 'created')

if (vm.$options.el) {
  vm.$mount(vm.$options.el) // 触发挂载
}

3. 响应式系统深度解析

数据观测实现

function initData(vm) {
  let data = vm.$options.data;
  data = vm._data = typeof data === 'function' 
    ? getData(data, vm)
    : data || {};
  
  // 数据代理:vm.xxx -> vm._data.xxx
  proxy(vm, '_data', key);
  
  // 核心响应式处理
  observe(data);
}

依赖收集原理

class Observer {
  constructor(value) {
    this.value = value;
    this.dep = new Dep();
    
    if (Array.isArray(value)) {
      // 数组的特殊处理
      protoAugment(value, arrayMethods);
      this.observeArray(value);
    } else {
      // 对象的处理
      this.walk(value);
    }
  }
  
  walk(obj) {
    Object.keys(obj).forEach(key => {
      defineReactive(obj, key, obj[key]);
    });
  }
}

4. 依赖收集的完整闭环

function defineReactive(obj, key, val) {
  const dep = new Dep();
  
  let childOb = observe(val); // 递归观察子属性
  
  Object.defineProperty(obj, key, {
    get() {
      if (Dep.target) {
        dep.depend();        // 收集依赖
        if (childOb) {
          childOb.dep.depend(); // 子对象依赖收集
          if (Array.isArray(val)) {
            dependArray(val);   // 数组元素依赖收集
          }
        }
      }
      return val;
    },
    set(newVal) {
      if (newVal === val) return;
      val = newVal;
      childOb = observe(newVal); // 新值观察
      dep.notify();             // 触发更新
    }
  });
}

5. 虚拟DOM与渲染系统

在 $mount 阶段:

Vue.prototype.$mount = function(el) {
  el = el && query(el);
  
  // 防止重复挂载
  if (el === document.body || el === document.documentElement) {
    warn("Do not mount Vue to <html> or <body>");
    return this;
  }
  
  const options = this.$options;
  
  // 解析模板/el到render函数
  if (!options.render) {
    let template = options.template;
    if (template) {
      // 处理各种模板来源
    } else if (el) {
      template = getOuterHTML(el);
    }
    
    if (template) {
      // 编译核心流程
      const { render, staticRenderFns } = compileToFunctions(
        template,
        { ... },
        this
      );
      options.render = render;
      options.staticRenderFns = staticRenderFns;
    }
  }
  
  // 调用真正的挂载方法
  return mount.call(this, el);
};

5. 完整生命周期图示

new Vue()
│
├─ beforeCreate
│   ├─ 初始化事件/生命周期
│   └─ 未初始化响应式数据
│
├─ created
│   ├─ 已完成响应式观测
│   ├─ 计算属性/methods/watch已配置
│   └─ 未挂载DOM
│
├─ beforeMount
│   ├─ 编译模板为render函数
│   └─ 未执行DOM挂载
│
├─ mounted
│   ├─ 已完成DOM挂载
│   └─ $el可用
│
├─ beforeUpdate (数据变化时)
│
├─ updated
│
├─ beforeDestroy
│
└─ destroyed

6. 性能优化相关设计

  1. 异步更新队列

    // 变更检测是异步的
    Vue.nextTick(() => {
      // DOM更新完成
    })
  2. 组件级更新

    • 每个组件对应一个渲染 Watcher

    • 通过 shouldUpdate 钩子优化

  3. 静态树提升

    • 编译时标记静态子树

    • 跳过不必要的 diff 比对

7. 与其他设计模式的对比

特性VueReactAngular
初始化方式选项式/组合式API函数式组件装饰器类
响应式原理getter/setter手动setStateZone.js脏检查
变更检测自动依赖追踪手动/自动混合脏检查循环
机制Vue 2.xReact 16+Angular
变更检测细粒度依赖追踪虚拟DOM diff脏检查循环
更新粒度组件级纤维节点级组件级
数据绑定双向绑定单向数据流双向绑定
异步更新nextTick 队列优先级调度Zone.js 控制
模板处理编译时优化JSX 运行时处理编译时优化

理解 new Vue() 的完整初始化过程,有助于:

  • 更高效地使用Vue框架

  • 更好地调试应用问题

  • 编写更合理的组件代码

  • 实现高级定制功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值