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.xxxproxy(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框架

  • 更好地调试应用问题

  • 编写更合理的组件代码

  • 实现高级定制功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/912694.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/912694.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最简安装SUSE15SP7导致大部分命令缺失

我嘞个去~~~明明选择Enable了ssh&#xff0c;结果也没给装。 俺习惯使用NetworkManager管理网络&#xff0c;没给装&#xff0c;用不了nmcli和nmtui。不高兴归不高兴&#xff0c;最简安装的话&#xff0c;也情有可原。我嘞个去去~~连ping、vi都没有装&#xff0c;这也太简了。…

Vue-14-前端框架Vue之应用基础嵌套路由和路由传参

文章目录 1 嵌套路由1.1 News.vue1.2 Detail.vue1.3 router/index.ts2 路由传参2.1 query参数2.1.1 News.vue(传递参数)2.1.2 Detail.vue(接收参数)2.2 params参数2.2.1 router/index.ts(需要提前占位)2.2.2 News.vue(传递参数)2.2.3 Detail.vue(接收参数)2.3 props配置2.3.1 r…

Python网安-ftp服务暴力破解(仅供学习)

目录 源码在这里 需要导入的模块 连接ftp&#xff0c;并设置密码本和线程 核心代码 设置线程 源码在这里 https://github.com/Wist-fully/Attack/tree/cracker 需要导入的模块 import ftplib from threading import Thread import queue 连接ftp&#xff0c;并设置密码…

ES6数组的`flat()`和`flatMap()`函数用法

今天给大家分享ES6中两个超实用的数组函数&#xff1a;flat()和flatMap()&#xff0c;学会它们能让数组处理变得更轻松&#xff01; 1. flat()函数 1.1 基本介绍 flat()用于将嵌套数组"拍平"&#xff0c;即将多维数组转换为一维数组。 1.2 语法 const newArray …

upload-labs靶场通关详解:第15-16关

第十五关 getimagesize函数验证 一、分析源代码 function isImage($filename){$types .jpeg|.png|.gif;if(file_exists($filename)){$info getimagesize($filename);$ext image_type_to_extension($info[2]);if(stripos($types,$ext)>0){return $ext;}else{return false…

【Linux】基础IO流

好的代码自己会说话&#xff0c;清晰的逻辑与优雅的结构&#xff0c;是程序员与世界对话的方式。 前言 这是我自己学习Linux系统编程的第五篇笔记。后期我会继续把Linux系统编程笔记开源至博客上。 上一期笔记是关于进程&#xff1a; 【Linux】进程-CSDN博客https://blog.csdn…

【C语言】学习过程教训与经验杂谈:思想准备、知识回顾(二)

&#x1f525;个人主页&#xff1a;艾莉丝努力练剑 ❄专栏传送门&#xff1a;《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题 &#x1f349;学习方向&#xff1a;C/C方向 ⭐️人生格言&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为…

AD8021ARZ-REEL7【ADI】300MHz低噪声运放放大器,高频信号处理的性价比之选!

AD8021ARZ-REEL7&#xff08;ADI&#xff09;产品解析与推广文案 1. 产品概述 AD8021ARZ-REEL7 是 Analog Devices Inc.&#xff08;ADI&#xff09; 推出的一款 高速、低噪声运算放大器&#xff08;Op-Amp&#xff09;&#xff0c;属于 ADI的高性能放大器系列&#xff0c;专为…

WPF学习笔记(11)数据模板DataTemplate与数据模板选择器DataTemplateSelector

数据模板DataTemplate与数据模板选择器DataTemplateSelector 一、DataTemplate1. DataTemplate概述2. DataTemplate详解 二、DataTemplateSelector1. DataTemplateSelector概述2. DataTemplateSelector详解 总结 一、DataTemplate 1. DataTemplate概述 DataTemplate 表示数据…

【V6.0 - 听觉篇】当AI学会“听”:用声音特征捕捉视频的“情绪爽点”

系列回顾&#xff1a; 在上一篇 《AI的“火眼金睛”&#xff1a;用OpenCV和SHAP洞察“第一眼缘”》 中&#xff0c;我们成功地让AI拥有了视觉&#xff0c;它已经能像一个严苛的“质检员”一样&#xff0c;评判我视频的画质和动态感。 但我的焦虑并没有完全消除。因为我发现&a…

(5)pytest-yield操作

1. 简介 上一篇中&#xff0c;我们刚刚实现了在每个用例之前执行初始化操作&#xff0c;那么用例执行完之后如需要清除数据&#xff08;或还原&#xff09;操作&#xff0c;可以使用 yield 来实现。fixture通过scope参数控制setup级别&#xff0c;既然有setup作为用例之前前的操…

C++中的cmath库

在C编程中&#xff0c;数值计算是科学计算、工程应用及算法开发的基础。cmath库作为C标准库的重要组成部分&#xff0c;提供了丰富的数学函数和工具&#xff0c;能够高效处理各种数值计算任务。本文将全面解析cmath库的核心功能&#xff0c;并通过实战案例展示其强大威力。 一…

python包管理工具uv VS pip

在 Python 中&#xff0c;uv 和 pip 都是包管理工具&#xff0c;但它们的定位和特性有所不同。以下是主要区别&#xff1a; 1. pip&#xff08;传统工具&#xff09; 定位&#xff1a;Python 官方的包安装工具&#xff0c;是 Python 生态中最基础的包管理器。特点&#xff1a;…

OpenCv基础(C++)

1.图像读取与显示 #include<opencv2/opencv.hpp> using namespace cv;Mat src imread("C:/Users/16385/Desktop/new/photo/1.jpg");//读取图像 Mat src imread("C:/Users/16385/Desktop/new/photo/1.jpg",IMREAD_GRAYSCALE); //将读取的图像转为灰…

MySQL非阻塞创建索引的方法

文章目录 1. Online DDL (MySQL 5.6)2. pt-online-schema-change 工具3. gh-ost 工具4. 对于MySQL 8.0注意事项 在MySQL中创建大型表索引时&#xff0c;传统方式会阻塞表的写操作&#xff0c;影响生产环境使用。以下是几种非阻塞创建索引的方法&#xff1a; 1. Online DDL (My…

数字雨动画背景

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>数字雨动画背景</title><style>* {m…

分布式锁的概念与应用场景

一、分布式锁的核心概念 分布式锁是一种在分布式系统环境下&#xff0c;用于保证多个进程/节点对共享资源实现互斥访问的机制。其本质是通过某种中间件&#xff08;如Redis、ZooKeeper等&#xff09;实现跨节点的锁控制&#xff0c;确保在分布式环境中&#xff0c;同一时刻只有…

js代码09

题目 好的&#xff0c;我们继续。 在上一个练习中&#xff0c;我们深入探讨了 this 的复杂性。你会发现&#xff0c;ES6 引入的 class 语法在很大程度上就是为了简化 this 的使用&#xff0c;并为 JavaScript 提供一个更清晰、更熟悉的面向对象编程&#xff08;OOP&#xff0…

基于Airtest的App数据爬取实战:突破传统爬虫的边界

引言:App数据爬取的技术困境 在当今移动优先的时代,App已成为企业核心数据载体,然而​​传统爬虫技术​​在App数据获取上面临三大难题: ​​协议层屏障​​:加密HTTPS、SSL Pinning等技术阻断中间人攻击​​渲染层障碍​​:React Native、Flutter等跨平台框架使DOM解析…

【LeetCode 热题 100】560. 和为 K 的子数组——(解法一)前缀和+暴力

Problem: 560. 和为 K 的子数组 题目&#xff1a;给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。子数组是数组中元素的连续非空序列。 【LeetCode 热题 100】560. 和为 K 的子数组——&#xff08;解法二&#xff09;前缀和…