【vue2源码】阶段一:Vue 初始化
文章目录
- 一、项目目录
- 1、主目录
- 2、打包入口
- 二、构造函数Vue的初始化
- 1、创建 Vue 构造函数
- 2、初始化内容分析
- 2.1 initMixin
- 2.2 stateMixin
- 2.3 eventsMixin
- 2.4 lifecycleMixin
- 2.5 renderMixin
一、项目目录
源码版本:2.7.16
1、主目录
src
|-- compiler # 包含与模板编译相关的代码。它将模板字符串转换成渲染函数 render。
|-- core # 核心代码|-- instance # Vue.js 实例的构造函数和原型方法|-- observer # 响应式系统实现,负责数据变化侦测|-- vdom # 虚拟 dom 的创建和更新算法|-- components # 内置组件,如<keep-alive>|-- global-api # 全局 API 方法,如 Vue.component
|-- platforms # 不同平台的入口,包括 web 和 weex
|-- shared # 整个项目共用的工具函数或辅助函数
|-- types # 包含 TypeScript 类型定义的目录
2、打包入口
查看 package.json
"scripts": {"dev": "rollup -w -c scripts/config.js --environment TARGET:full-dev"
}
执行 npm run dev 会进入 scripts/config.js 的打包配置,进入 config.js 找到 full-dev :
'full-dev': {entry: resolve('web/entry-runtime-with-compiler.ts'),dest: resolve('dist/vue.js'),format: 'umd',env: 'development',alias: { he: './entity-decoder' },banner},
可以看到打包入口文件在 web/entry-runtime-with-compiler.ts :
从这边开始源码入手:
import Vue from './runtime-with-compiler'
import * as vca from 'v3'
import { extend } from 'shared/util'extend(Vue, vca)import { effect } from 'v3/reactivity/effect'
Vue.effect = effectexport default Vue
二、构造函数Vue的初始化
1、创建 Vue 构造函数
源码路径:src/core/instance/index.ts
import { eventsMixin } from "./events";
import { initMixin } from "./init";
import { lifecycleMixin } from "./lifecycle";
import { renderMixin } from "./render";
import { stateMixin } from "./state";// Vue 的构造函数
function Vue(options) {this._init(options);
}//@ts-expect-error Vue has function type
initMixin(Vue);
//@ts-expect-error Vue has function type
stateMixin(Vue);
//@ts-expect-error Vue has function type
eventsMixin(Vue);
//@ts-expect-error Vue has function type
lifecycleMixin(Vue);//@ts-expect-error Vue has function type
renderMixin(Vue);export default Vue;
2、初始化内容分析
2.1 initMixin
initMixin 函数负责向 Vue 的原型添加一个 _init 方法,这个方法是Vue实例的私有方法,并且是 Vue 实例初始化过程的起点
源码位置:src/core/instance/init.ts
export function initMixin(Vue: typeof Component) {Vue.prototype._init = function (options?: Record<string, any>) {const vm: Component = thisvm._uid = uid++ // 设置一个唯一的标识符 _uid,用于标识组件实例vm._isVue = true // 这是一个标记,用来简单判断这是一个 Vue 实例// avoid instances from being observedvm.__v_skip = true // 设置一个标志 __v_skip,避免 Vue 实例被响应式系统观察// 创建一个效果范围 _scope,并设置其父作用域为 undefinedvm._scope = new EffectScope(true /* detached */)vm._scope.parent = undefinedvm._scope._vm = true// 合并传入的 optionsif (options && options._isComponent) {// optimize internal component instantiation// since dynamic options merging is pretty slow, and none of the// internal component options needs special treatment.initInternalComponent(vm, options as any)} else {vm.$options = mergeOptions(resolveConstructorOptions(vm.constructor as any),options || {},vm)}// _self 属性也被引用到实例自身,目的是使得实例可以在内部作用域中访问到自己。vm._self = vminitLifecycle(vm) // 初始化实例的生命周期initEvents(vm) // 初始化实例的事件系统initRender(vm) // 初始化渲染函数// callHook 调用 'beforeCreate' 生命周期钩子。callHook(vm, 'beforeCreate', undefined, false /* setContext */)// initInjections 初始化 inject 选项(注入依赖)initInjections(vm) // resolve injections before data/props// 初始化实例的状态,包括 data, props, computed 等。initState(vm)// initProvide 处理 provide 选项(提供依赖)initProvide(vm) // resolve provide after data/props// callHook 再次被调用以触发 'created' 生命周期钩子callHook(vm, 'created')// 如果 vm.$options.el 存在,那么调用 vm.$mount 来挂载实例if (vm.$options.el) {vm.$mount(vm.$options.el)}}
}
2.2 stateMixin
stateMixin 函数的作用是给 Vue 实例的原型添加一些与状态相关的实例方法,即操作数据和观察者的方法。这包括 $data 和 $props 访问器属性,以及用于观察和修改响应式数据的实例方法 $set、 $delete 和 $watch
源码位置:src/core/instance/state.ts
export function stateMixin(Vue: typeof Component) {// flow somehow has problems with directly declared definition object// when using Object.defineProperty, so we have to procedurally build up// the object here.const dataDef: any = {}dataDef.get = function () {return this._data}const propsDef: any = {}propsDef.get = function () {return this._props}// 响应式系统中代理了实例数据对象 data 和 props 对象的存取器属性。// 这些属性是只读的,提供了访问组件数据和传入属性的一致化接口。Object.defineProperty(Vue.prototype, '$data', dataDef)Object.defineProperty(Vue.prototype, '$props', propsDef)// 实例方法 $set 允许你向响应式对象添加一个属性,并确保这个新属性也是响应式的Vue.prototype.$set = set// 实例方法 $delete 允许你从响应式对象中删除一个属性。// 这和 delete 操作符的使用相比,$delete 还会触发视图更新Vue.prototype.$delete = del//set 和 del 是 Vue 的全局 API 方法,提供了 $set 和 $delete 的具体实现// $watch 用于观察 Vue 实例中的数据变更。该方法返回一个取消观察函数,用于停止触发回调// 这个方法接收观察的数据表达式或函数作为第一个参数,以及当被观察的数据发生变化时的回调函数作为第二个参数。Vue.prototype.$watch = function (expOrFn: string | (() => any),cb: any,options?: Record<string, any>): Function {const vm: Component = thisif (isPlainObject(cb)) {return createWatcher(vm, expOrFn, cb, options)}options = options || {}options.user = trueconst watcher = new Watcher(vm, expOrFn, cb, options)if (options.immediate) {const info = `callback for immediate watcher "${watcher.expression}"`pushTarget()invokeWithErrorHandling(cb, vm, [watcher.value], vm, info)popTarget()}return function unwatchFn() {watcher.teardown()}}
}
2.3 eventsMixin
eventsMixin 函数负责向 Vue 的原型添加事件相关的方法。这些方法允许组件实例监听和触发自定义事件,是 Vue 组件通信机制的核心部分。
源码位置: src/core/instance/events.ts
eventsMixin 的基本结构:
export function eventsMixin (Vue: typeof Component) {// 用于监听当前实例上的自定义事件。事件可以由‘vm.emit` 触发。回调函数会接收所有传入事件触发函数的额外参数。Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {// ...}// 监听一个自定义事件,但只触发一次,一旦触发之后,监听器会被移除Vue.prototype.$once = function (event: string, fn: Function): Component {// ...}// 移除自定义事件监听器。// 如果没有提供参数,则移除所有的事件监听器;// 如果只提供了事件,则移除该事件所有的监听器;// 如果同时提供了事件与回调,则只移除这个回调的监听器。Vue.prototype.$off = function (event?: string | Array<string>, fn?: Function): Component {// ...}// 触发当前实例上的事件。附加参数都会传给监听器回调Vue.prototype.$emit = function (event: string): Component {// ...}
}
2.4 lifecycleMixin
lifecycleMixin 函数的作用是向 Vue 的原型中添加与组件生命周期相关的方法。这些方法主要用于在组件的不同生命周期阶段上触发相关的生命周期钩子
源码位置:src/core/instance/lifecycle.ts
lifecycleMixin 的基本结构:
export function lifecycleMixin (Vue: typeof Component) {// 这个方法用来根据虚拟 DOM 树来更新 DOM。// 它是响应系统检测到数据变化后调用渲染函数生成新的虚拟 DOM 树,并与旧的虚拟 DOM 树进行比对之后的更新处理函数Vue.prototype._update = function (vnode: VNode, hydrating?: boolean): void {// ...更新逻辑}// 这个方法会迫使组件重新渲染。// 通常,你不需要调用这个方法,因为 Vue 的响应系统会在数据变化时自动进行更新。但是,在一些特殊情况下,可能需要此方法来强制组件重新渲染。Vue.prototype.$forceUpdate = function (): void {// ...强制更新逻辑}// 用于完全销毁一个实例,清理它与其他实例的连接,解绑它的全部指令及事件监听器。Vue.prototype.$destroy = function (): void {// ...销毁逻辑}
}
2.5 renderMixin
renderMixin 函数在 Vue.js 源代码中的作用是将与渲染相关的一些方法和属性混入到 Vue 的原型中。这些方法和属性是渲染过程中使用的,包括生成虚拟 DOM 和更新组件实例的渲染
源码位置: src/core/instance/render.ts
renderMixin 的基本结构:
export function renderMixin (Vue: Class<Component>) {// install runtime convenience helpersVue.prototype._o = markOnceVue.prototype._n = toNumberVue.prototype._s = toString// ... more helper methods// 将 $nextTick 方法添加到原型// 提供一个在下次 DOM 更新循环结束后执行延迟回调的方法。// 这在修改数据之后,你想基于更新后的 DOM 状态来执行操作时非常有用。Vue.prototype.$nextTick = function(fn: Function): void {return nextTick(fn, this)}// 这是一个内部方法,用来生成组件的虚拟 DOM 树(Virtual DOM Tree)// 它会调用开发者编写的 render 函数(或者编译时由模板转换而成的 render 函数)来生成虚拟节点(VNodes)。这个过程是响应式系统追踪依赖关系的一部分,并且当数据变更时会触发组件的重新渲染。Vue.prototype._render = function(): VNode {// 生成 VNode 的逻辑}
}
相关文章:
【vue2源码】阶段一:Vue 初始化
文章目录 一、项目目录1、主目录2、打包入口 二、构造函数Vue的初始化1、创建 Vue 构造函数2、初始化内容分析2.1 initMixin2.2 stateMixin2.3 eventsMixin2.4 lifecycleMixin2.5 renderMixin 一、项目目录 源码版本:2.7.16 1、主目录 src |-- compiler # 包…...
14.java集合
文章目录 概念Collection 接口概念示例 Iterator 迭代器基本操作:并发修改异常增强循环遍历数组:遍历集合:遍历字符串:限制 list接口ListIteratorArrayList创建 ArrayList:添加元素:获取元素:修…...
二叉树顺序结构堆实现
目录 Test.c测试代码 test1 test2 test3 🎇Test.c总代码 Heap.h头文件&函数声明 头文件 函数声明 🎇Heap.h总代码 Heap.c函数实现 ☁HeapInit初始化 ☁HeapDestroy销毁 ☁HeapPush插入数据 【1】插入数据 【2】向上调整Adjustup❗ …...
正则表达式 与文本三剑客(sed grep awk)
一,正则表达式 (一)正则表达式相关定义 1,正则表达式含义 REGEXP: Regular Expressions,由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意…...
【XR806开发板试用】全志 XR806 OpenHarmony 鸿蒙系统固件烧录
大家好,我是极智视界,本教程详细记录了全志 XR806 OpenHarmony 鸿蒙系统固件烧录的方法。 在上一篇文章《【嵌入式AI】全志 XR806 OpenHarmony 鸿蒙系统固件编译》中咱们已经编译生成了系统镜像,这里把这个编译出来的镜像烧录到 XR806 板子里…...
linux环境安装git、maven、jenkins等
重启 jenkins的命令: systemctl start jenkins 如果没有vim 命令 可以使用 yum install vim 安装 vim git 下载包地址 https://www.kernel.org/pub/software/scm/git/git-2.28.0.tar.gz 1.安装依赖环境: yum install -y curl-devel expat-devel ge…...
RabbitMQ快速上手
首先他的需求实在什么地方。我美哟明显的感受到。 它给我的最大感受就是脱裤子放屁——多此一举,的感觉。 他将信息发送给服务端中间件。在由MQ服务器发送消息。 服务器会监听消息。 但是它不仅仅局限于削峰填谷和稳定发送信息的功能,它还有其他重要…...
SpringBoot activemq收发消息、配置及原理
SpringBoot集成消息处理框架 Spring framework提供了对JMS和AMQP消息框架的无缝集成,为Spring项目使用消息处理框架提供了极大的便利。 与Spring framework相比,Spring Boot更近了一步,通过auto-configuration机制实现了对jms及amqp主流框架…...
视频智能识别安全帽佩戴系统-工地安全帽佩戴识别算法---豌豆云
视频智能识别安全帽佩戴系统能够从繁杂的工地、煤矿、车间等场景下同时对多个目标是否戴安全帽穿反光衣进行实时识别。 当视频智能识别安全帽佩戴系统发现作业人员没有戴安全帽、穿反光衣或者戴安全带,系统会及时报警提醒,并抓拍存档。 视频智能识别安…...
指针的深入理解(三)
这一节主要使用复习回调函数, 利用冒泡模拟实现qsort函数。 qsort 排序使用冒泡排序,主要难点在于运用元素个数和字节数以及基地址控制元素的比较: if里面使用了一个判断函数,qsort可以排序任意的数据,原因就是因为可…...
【Linux C | 网络编程】详细介绍 “三次握手(建立连接)、四次挥手(终止连接)、TCP状态”
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…...
主从数据库MySQL服务重启步骤与注意事项
主从数据库MySQL服务重启步骤与注意事项 实验环境: 172.20.26.34 (主应用服务器) 172.20.26.26 (备应用服务器) 172.20.26.37 (主库服务器) 172.20.26.38 (从库服务器&…...
netlink学习
netlink是什么 netlink是Linux内核中的一种进程间通信(IPC)机制。它允许内核空间与用户空间之间,以及用户空间进程之间进行双向通信。 内核里的很多子系统使用netlink通信,包括网络管理(Routing,Netfilt…...
地理空间分析10——空间数据分析中的地理编码与Python
目录 写在开头1. 地理编码基础1.1 地理编码的基本原理1.1.1 坐标系统1.1.2 地名解析1.1.3 编码算法1.2 Python中使用地理编码的基础知识1.2.1 百度地图API1.2.2 高德地图API1.2.3 腾讯地图API1.3 Python中实现代码2. 逆地理编码2.1 利用Python进行逆地理编码2.1.1 获取高德地图…...
使用“快速开始”将数据传输到新的 iPhone 或 iPad
使用“快速开始”将数据传输到新的 iPhone 或 iPad 使用 iPhone 或 iPad 自动设置你的新 iOS 设备。 使用“快速开始”的过程会同时占用两台设备,因此请务必选择在几分钟内都不需要使用当前设备的时候进行设置。 确保你当前的设备已连接到无线局域网,并…...
计算机网络(第六版)复习提纲13
前同步码,七位1010交替出现,帧开始码:10101011 为什么没有帧结束?曼彻斯特码传播完成后,维持高电平,不再跳变,因此不必要设置帧结束。 3.无效的MAC帧 i.数据字段的长度与长度字段的值不一致&…...
[office] excel2010双向条形图制作 #经验分享#微信
excel2010双向条形图制作 本教程为大家介绍一下excel2010中excel2010双向条形图制作方法。 1.选中工作区域 2.点击插入-->图表,选择条形图 3.为美观可将中间竖线可去掉 4.方法是选中竖线,右击-->删除 5.接下来将图例靠上,选中图例,右击-->设置图例格式-->图例选项…...
优雅管理多线程异步任务 - 永动异步任务
引言 在现代应用程序中,经常需要处理长时间运行的异步任务,如消息推送、定时任务等。为了确保这些异步任务能够安全可靠地执行,我们需要一种优雅的管理方式。本文将介绍一种基于线程池的多线程异步任务管理方案,并详细讨论任务的优雅关闭。 1. 多线程异步任务管理的需求 …...
软考笔记--分布式数据库
分布式数据库系统是数据库技术与网络技术相结合的产物,其基本思想是将传统的集中式数据库中的数据分布于网络上的多台计算机中。分布式数据库系统通常使用较小的计算机系统,每台计算机可单独放在一个地方,每台计算机中都有DBMS的一份完整的复…...
vue项目中路由懒加载的三种方式
1 . vue异步组件技术 异步加载 vue-router配置路由 , 使用vue的异步组件技术 , 可以实现按需加载 . 但是,这种情况下一个组件生成一个js文件 /* vue异步组件技术 */ { path: /home, name: home, component: resolve > require([/components/home],resolve) }, { path…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁
赛门铁克威胁猎手团队最新报告披露,数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据,严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能,但SEMR…...
规则与人性的天平——由高考迟到事件引发的思考
当那位身着校服的考生在考场关闭1分钟后狂奔而至,他涨红的脸上写满绝望。铁门内秒针划过的弧度,成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定",构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...
