[{"data":1,"prerenderedAt":1920},["ShallowReactive",2],{"page-\u002Fvue\u002Fvue源码解读笔记共享工具库":3},{"id":4,"title":5,"body":6,"description":1202,"extension":1914,"meta":1915,"navigation":1320,"path":1916,"seo":1917,"stem":1918,"__hash__":1919},"content\u002FVue\u002Fvue源码解读笔记共享工具库.md","Vue源码解读笔记共享工具库",{"type":7,"value":8,"toc":1898},"minimark",[9,14,18,41,44,56,85,88,102,105,134,137,172,175,214,217,229,232,235,240,251,256,267,270,295,298,301,312,315,326,329,339,342,353,356,358,369,373,399,403,406,420,423,427,430,437,440,455,461,472,478,492,498,509,512,520,526,534,537,545,551,559,565,576,579,587,593,604,607,618,622,625,630,641,646,663,671,914,919,933,938,949,953,957,992,1004,1032,1036,1083,1087,1104,1108,1124,1128,1142,1146,1162,1166,1170,1181,1185,1196,1616,1639,1673,1676,1680,1691,1695,1699,1710,1714,1725,1729,1739,1743,1747,1757,1761,1771,1775,1785,1789,1793,1803,1807,1817,1821,1825,1835,1839,1849,1853,1857,1867,1871,1881,1885,1895],[10,11,13],"h2",{"id":12},"学习路径建议","🎯 学习路径建议",[15,16,17],"p",{},"第一阶段：基础架构理解 (1-2周)",[19,20,21],"ol",{},[22,23,24,25,29,30,33,34,37,38],"li",{},"从 packages\u002Fshared\u002F 开始packages\u002Fshared\u002Fsrc\u002F├── index.ts     ",[26,27,28],"em",{},"# 工具函数入口","├── utils.ts     ",[26,31,32],{},"# 基础工具函数","├── types.ts     ",[26,35,36],{},"# 类型定义","└── constants.ts   ",[26,39,40],{},"# 常量定义",[15,42,43],{},"为什么从这里开始？",[45,46,47,50,53],"ul",{},[22,48,49],{},"代码量相对较小，容易理解",[22,51,52],{},"被其他所有包依赖，是基础",[22,54,55],{},"包含大量工具函数，学习价值高",[19,57,59],{"start":58},2,[22,60,61,62,65,66,69,70,73,74,77,78,81,82],{},"学习 packages\u002Freactivity\u002Fpackages\u002Freactivity\u002Fsrc\u002F├── index.ts     ",[26,63,64],{},"# 响应式系统入口","├── reactive.ts    ",[26,67,68],{},"# reactive API","├── ref.ts      ",[26,71,72],{},"# ref API","├── computed.ts   ",[26,75,76],{},"# computed API","├── watch.ts     ",[26,79,80],{},"# watch API","└── effect.ts    ",[26,83,84],{},"# 副作用系统",[15,86,87],{},"重点学习：",[45,89,90,93,96,99],{},[22,91,92],{},"reactive() 的实现原理",[22,94,95],{},"ref() 和 reactive() 的区别",[22,97,98],{},"effect 的依赖收集和触发机制",[22,100,101],{},"computed 的缓存机制",[15,103,104],{},"第二阶段：运行时核心 (2-3周)",[19,106,108],{"start":107},3,[22,109,110,111,114,115,118,119,122,123,126,127,130,131],{},"深入 packages\u002Fruntime-core\u002Fpackages\u002Fruntime-core\u002Fsrc\u002F├── apiCreateApp.ts  ",[26,112,113],{},"# 应用创建","├── component.ts   ",[26,116,117],{},"# 组件定义","├── vnode.ts     ",[26,120,121],{},"# 虚拟节点","├── renderer.ts   ",[26,124,125],{},"# 渲染器","├── scheduler.ts   ",[26,128,129],{},"# 调度器","└── h.ts      ",[26,132,133],{},"# h 函数",[15,135,136],{},"学习顺序：",[19,138,139,142,145,148,151,154],{},[22,140,141],{},"vnode.ts - 理解虚拟 DOM 结构",[22,143,144],{},"component.ts - 组件实例和生命周期",[22,146,147],{},"apiCreateApp.ts - 应用创建流程",[22,149,150],{},"renderer.ts - 渲染逻辑",[22,152,153],{},"scheduler.ts - 更新调度",[22,155,156,157,160,161,164,165,168,169],{},"学习 packages\u002Fruntime-dom\u002Fpackages\u002Fruntime-dom\u002Fsrc\u002F├── index.ts     ",[26,158,159],{},"# DOM 运行时入口","├── nodeOps.ts   ",[26,162,163],{},"# DOM 操作","├── patchProp.ts  ",[26,166,167],{},"# 属性更新","└── renderer.ts   ",[26,170,171],{},"# DOM 渲染器",[15,173,174],{},"第三阶段：编译器 (3-4周)",[19,176,178,196],{"start":177},5,[22,179,180,181,184,185,188,189,192,193],{},"编译器核心 packages\u002Fcompiler-core\u002Fpackages\u002Fcompiler-core\u002Fsrc\u002F├── parse.ts    ",[26,182,183],{},"# 模板解析","├── transform.ts  ",[26,186,187],{},"# AST 转换","├── codegen.ts   ",[26,190,191],{},"# 代码生成","└── transforms\u002F  ",[26,194,195],{},"# 各种转换器",[22,197,198,199,202,203,206,207,210,211],{},"SFC 编译器 packages\u002Fcompiler-sfc\u002Fpackages\u002Fcompiler-sfc\u002Fsrc\u002F├── parse.ts    ",[26,200,201],{},"# SFC 解析","├── compileScript.ts ",[26,204,205],{},"# 脚本编译","├── compileTemplate.ts ",[26,208,209],{},"# 模板编译","└── compileStyle.ts ",[26,212,213],{},"# 样式编译",[15,215,216],{},"第四阶段：高级特性 (2-3周)",[19,218,220,223,226],{"start":219},7,[22,221,222],{},"服务端渲染 packages\u002Fserver-renderer\u002F",[22,224,225],{},"兼容性层 packages\u002Fruntime-core\u002Fsrc\u002Fcompat\u002F",[22,227,228],{},"主入口 packages\u002Fvue\u002F",[15,230,231],{},"🛠️ 学习工具和方法",[15,233,234],{},"推荐的学习工具：",[19,236,237],{},[22,238,239],{},"VS Code 插件：",[45,241,242,245,248],{},[22,243,244],{},"TypeScript Importer",[22,246,247],{},"Vue Language Features (Volar)",[22,249,250],{},"GitLens",[19,252,253],{},[22,254,255],{},"调试工具：",[45,257,258,261,264],{},[22,259,260],{},"Chrome DevTools",[22,262,263],{},"Vue DevTools",[22,265,266],{},"Node.js 调试器",[15,268,269],{},"学习方法：",[19,271,272,283,286],{},[22,273,274,275,279,280,282],{},"从测试用例开始*# 每个包都有对应的测试*packages\u002Freactivity\u002F",[276,277,278],"strong",{},"tests","\u002Fpackages\u002Fruntime-core\u002F",[276,281,278],{},"\u002F",[22,284,285],{},"创建学习项目*# 创建简单的测试项目*mkdir vue-source-learningcd vue-source-learningnpm init -ynpm install vue@next",[22,287,288,289,292,293],{},"断点调试*\u002F\u002F 在关键函数处打断点*import { reactive, ref } from 'vue'const state = reactive({ count: 0 }) ",[26,290,291],{},"\u002F\u002F 在这里打断点","const count = ref(0) ",[26,294,291],{},[15,296,297],{},"📚 学习资源",[15,299,300],{},"官方资源：",[19,302,303,306,309],{},[22,304,305],{},"Vue 3 官方文档",[22,307,308],{},"Vue 3 迁移指南",[22,310,311],{},"Vue RFC",[15,313,314],{},"推荐阅读顺序：",[19,316,317,320,323],{},[22,318,319],{},"先读 Vue 3 官方文档，理解 API 用法",[22,321,322],{},"再看源码实现，理解内部原理",[22,324,325],{},"结合测试用例，验证理解",[15,327,328],{},"🎯 具体学习建议",[15,330,331,332,335,336],{},"第一周：响应式系统*\u002F\u002F 学习目标：理解这个简单例子背后的原理*import { reactive, effect } from 'vue'const state = reactive({ count: 0 })effect(() => { console.log(state.count) ",[26,333,334],{},"\u002F\u002F 当 count 变化时自动执行","})state.count++ ",[26,337,338],{},"\u002F\u002F 触发 effect",[15,340,341],{},"关键问题：",[45,343,344,347,350],{},[22,345,346],{},"为什么 state.count++ 会自动触发 effect？",[22,348,349],{},"reactive 是如何工作的？",[22,351,352],{},"依赖收集是如何实现的？",[15,354,355],{},"第二周：组件系统*\u002F\u002F 学习目标：理解组件创建和渲染流程*import { createApp, h } from 'vue'const App = { render() {  return h('div', 'Hello Vue 3!') }}createApp(App).mount('#app')",[15,357,341],{},[45,359,360,363,366],{},[22,361,362],{},"createApp 做了什么？",[22,364,365],{},"h 函数如何创建虚拟节点？",[22,367,368],{},"组件是如何渲染到 DOM 的？",[10,370,372],{"id":371},"学习技巧","💡 学习技巧",[19,374,375,381,387,393,396],{},[22,376,377,378],{},"不要一开始就深入细节，",[276,379,380],{},"先理解整体架构",[22,382,383,384],{},"多画图，用",[276,385,386],{},"思维导图整理知识点",[22,388,389,390],{},"写笔记，",[276,391,392],{},"记录关键概念和实现原理",[22,394,395],{},"动手实践，修改源码看效果",[22,397,398],{},"参与社区，在 Vue 官方 Discord 或 GitHub 讨论",[10,400,402],{"id":401},"进阶学习","🚀 进阶学习",[15,404,405],{},"当你掌握了基础后，可以学习：",[45,407,408,411,414,417],{},[22,409,410],{},"Vue 3 的性能优化策略",[22,412,413],{},"编译器的优化技术",[22,415,416],{},"服务端渲染的实现",[22,418,419],{},"兼容性层的设计思路",[15,421,422],{},"记住：学习源码不是为了记住每一行代码，而是理解设计思路和实现原理。从简单到复杂，循序渐进，你一定能掌握 Vue 3 的精髓！",[424,425,426],"h3",{"id":426},"脚本内容",[15,428,429],{},"​\t首先是脚本部分，下面的是vuejs框架的管理、构建和发布维护项目工程使用的脚本：",[15,431,432],{},[433,434],"img",{"alt":435,"src":436},"image-20251013173755237",".\u002Fassets\u002Fimage-20251013173755237.png",[15,438,439],{},"aliases.js - 模块别名配置脚本",[45,441,442,448],{},[22,443,444,445],{},"用于配置 vitest 和 rollup 之间的",[276,446,447],{},"模块路径映射",[22,449,450,451,454],{},"动态",[276,452,453],{},"扫描 packages 目录","并生成别名映射",[15,456,457,458],{},"build.js - Vue 核心包",[276,459,460],{},"生产环境构建脚本",[45,462,463,466,469],{},[22,464,465],{},"支持并行构建多个包",[22,467,468],{},"生成不同格式的输出文件",[22,470,471],{},"集成文件大小报告和枚举内联优化",[15,473,474,475],{},"dev.js - Vue 核心包",[276,476,477],{},"开发环境构建脚本",[45,479,480,486],{},[22,481,482,483],{},"使用 esbuild 进行",[276,484,485],{},"快速构建",[22,487,488,489],{},"支持多种",[276,490,491],{},"输出格式和热重载",[15,493,494,495],{},"inline-enums.js - 枚举",[276,496,497],{},"内联优化脚本",[45,499,500,503,506],{},[22,501,502],{},"优化 TypeScript 枚举使用",[22,504,505],{},"减少最终打包文件大小",[22,507,508],{},"将枚举转换为全局替换",[15,510,511],{},"pre-dev-sfc.js - SFC 开发前检查脚本",[45,513,514,517],{},[22,515,516],{},"确保 SFC 相关包已构建完成",[22,518,519],{},"防止开发过程中出现模块找不到的问题",[15,521,522,523],{},"release.js - Vue 核心包",[276,524,525],{},"发布脚本",[45,527,528,531],{},[22,529,530],{},"自动化发布流程",[22,532,533],{},"版本管理、依赖更新、构建、测试、Git 操作和 npm 发布",[15,535,536],{},"setup-vitest.ts - Vitest 测试环境设置文件",[45,538,539,542],{},[22,540,541],{},"配置测试环境",[22,543,544],{},"添加自定义匹配器和全局模拟",[15,546,547,548],{},"size-report.js - 文件",[276,549,550],{},"大小报告生成脚本",[45,552,553,556],{},[22,554,555],{},"比较当前版本与之前版本的文件大小",[22,557,558],{},"支持多种压缩格式对比",[15,560,561,562],{},"usage-size.js - Vue ",[276,563,564],{},"用法大小分析脚本",[45,566,567,573],{},[22,568,569,570],{},"分析",[276,571,572],{},"不同用法场景下的包大小",[22,574,575],{},"测试 tree-shaking 效果",[15,577,578],{},"utils.js - 构建工具通用函数库",[45,580,581,584],{},[22,582,583],{},"包含构建脚本中的通用工具函数",[22,585,586],{},"包管理、目标匹配、命令执行等",[15,588,589,590],{},"verify-commit.js - Git ",[276,591,592],{},"提交信息验证脚本",[45,594,595,601],{},[22,596,597,598],{},"验证提交信息",[276,599,600],{},"是否符合项目规范",[22,602,603],{},"确保自动生成变更日志",[15,605,606],{},"verify-treeshaking.js - Tree-shaking 验证脚本",[45,608,609,612],{},[22,610,611],{},"验证生产构建的 tree-shaking 效果",[22,613,614,615],{},"确保",[276,616,617],{},"不包含不应该存在的代码",[424,619,621],{"id":620},"vue-核心项目的私有包和工具","Vue 核心项目的私有包和工具",[15,623,624],{},"​\t这些包不会发布到 npm，主要用于内部开发、测试和调试。",[19,626,627],{},[22,628,629],{},"dts-test\u002F - TypeScript 类型定义测试",[45,631,632,635,638],{},[22,633,634],{},"用于测试 Vue 核心包的 TypeScript 类型定义",[22,636,637],{},"确保类型定义在源码和构建后都能正常工作",[22,639,640],{},"包含各种 Vue API 的类型测试文件",[19,642,643],{},[22,644,645],{},"dts-built-test\u002F - 构建后类型测试",[45,647,648,654,657],{},[22,649,650,651],{},"专门用于",[276,652,653],{},"测试外部库使用 Vue 核心类型的情况",[22,655,656],{},"验证构建后的类型定义是否正常工作",[22,658,659,660],{},"解决类似 Vuetify 等",[276,661,662],{},"第三方库的类型兼容性问题",[19,664,665],{},[22,666,667,668],{},"template-explorer\u002F - ",[276,669,670],{},"模板编译器在线工具",[45,672,673,679,688,691],{},[22,674,675,676],{},"Vue 模板编译器的",[276,677,678],{},"实时探索工具",[22,680,681,682],{},"部署在 ",[683,684,685],"a",{"href":685,"rel":686},"https:\u002F\u002Ftemplate-explorer.vuejs.org",[687],"nofollow",[22,689,690],{},"用于展示和调试 Vue 模板编译过程。",[22,692,693,694,698,699,702,703,706,707,710,711,767,771,830,833,836,837,839,840,843,844,847,848,880,884],{},"Vue 文件（",[695,696,697],"code",{},".vue","）本质上是一个自定义的文件格式，它将 ",[695,700,701],{},"\u003Ctemplate>","、",[695,704,705],{},"\u003Cscript>"," 和 ",[695,708,709],{},"\u003Cstyle>"," 块组合在一起。",[45,712,713,722,731,741],{},[22,714,715,718,719,721],{},[276,716,717],{},"输入："," 原始 ",[695,720,697],{}," 文件内容。",[22,723,724,727,728],{},[276,725,726],{},"解析器："," ",[695,729,730],{},"@vue\u002Fcompiler-sfc",[22,732,733,736,737,740],{},[276,734,735],{},"过程："," SFC 解析器将文件内容",[276,738,739],{},"分割","成独立的块（称为 Block 或 Descriptor）。",[22,742,743,746,747],{},[276,744,745],{},"输出："," 一个描述符对象，包含：\n",[45,748,749,755,761],{},[22,750,751,754],{},[695,752,753],{},"template"," 块的内容 (HTML 字符串)。",[22,756,757,760],{},[695,758,759],{},"script"," 块的内容 (JS\u002FTS 代码)。",[22,762,763,766],{},[695,764,765],{},"style"," 块的内容 (CSS 代码)。",[768,769,770],"h4",{"id":770},"优化和代码生成",[45,772,773,778,786,821],{},[22,774,775,777],{},[276,776,717],{}," 模板 AST。",[22,779,780,727,783],{},[276,781,782],{},"编译器：",[695,784,785],{},"@vue\u002Fcompiler-dom",[22,787,788,790],{},[276,789,735],{},[19,791,792,802],{},[22,793,794,797,798,801],{},[276,795,796],{},"静态提升 (Static Hoisting)："," 编译器会遍历 AST，识别出那些",[276,799,800],{},"内容和属性永不改变的节点","（即静态节点）。",[22,803,804,807,808,811,812],{},[276,805,806],{},"代码生成："," 编译器根据优化后的 AST，生成 ",[276,809,810],{},"JavaScript 渲染函数（Render Function）","。\n",[45,813,814],{},[22,815,816,817,820],{},"这个渲染函数在运行时会被执行，并调用 ",[695,818,819],{},"createElementVNode"," (创建虚拟 DOM 节点 VNode) 等 API 来构建虚拟 DOM 树。",[22,822,823,825,826,829],{},[276,824,745],{}," 包含 ",[695,827,828],{},"render()"," 函数的 JavaScript 代码字符串。",[424,831,832],{"id":832},"最终产物",[834,835],"br",{},"在构建工具（如 Vite 或 Webpack 的 Vue Loader）中，最终的 ",[695,838,697],{}," 文件会被转换为一个 ",[276,841,842],{},"标准的 JavaScript 模块","，这个模块通常 ",[695,845,846],{},"export"," 出组件的定义对象，其中包含了：",[19,849,850,864],{},[22,851,852,853,855,856,859,860,863],{},"来自 ",[695,854,705],{}," 块的组件选项或 ",[695,857,858],{},"setup"," 函数（",[276,861,862],{},"JS\u002FTS 代码","）。",[22,865,852,866,868,869,876,877,863],{},[695,867,701],{}," 块的 ",[276,870,871,872,875],{},"编译后的 ",[695,873,874],{},"render"," 函数","（",[276,878,879],{},"JS 代码",[10,881,883],{"id":882},"总结为什么不是静态文件","总结：为什么不是“静态文件”？",[45,885,886,904],{},[22,887,888,891,892,895,896,899,900,903],{},[276,889,890],{},"不是静态 HTML\u002FCSS："," 编译器没有生成浏览器可以直接加载的 ",[695,893,894],{},".html"," 或 ",[695,897,898],{},".css"," 文件。它生成的是 ",[276,901,902],{},"JavaScript 代码","。",[22,905,906,909,910,913],{},[276,907,908],{},"是可执行的 JavaScript 渲染函数："," 这个生成的 JavaScript 代码（渲染函数）是",[276,911,912],{},"动态的","，它在组件挂载和更新时执行，根据组件的状态（响应式数据）创建或修补虚拟 DOM 树。",[19,915,916],{},[22,917,918],{},"sfc-playground\u002F - SFC 在线游乐场",[45,920,921,924,930],{},[22,922,923],{},"Vue 单文件组件的在线编辑和预览工具",[22,925,681,926],{},[683,927,928],{"href":928,"rel":929},"https:\u002F\u002Fplay.vuejs.org",[687],[22,931,932],{},"支持 Vue 3 的 SFC 开发体验",[19,934,935],{},[22,936,937],{},"vite-debug\u002F - Vite 调试工具",[45,939,940,943,946],{},[22,941,942],{},"用于调试与 @vitejs\u002Fplugin-vue 相关的问题",[22,944,945],{},"模拟生产环境，使用构建后的 dist 文件而非源码",[22,947,948],{},"解决只能在 Vite 环境中复现的问题",[424,950,952],{"id":951},"vue-3-核心框架的所有核心包","Vue 3 核心框架的所有核心包",[768,954,956],{"id":955},"_1-运行时包-runtime-packages","1. 运行时包 (Runtime Packages)",[45,958,959,962,968,971,976,979,985],{},[22,960,961],{},"vue\u002F - 主入口包，整合所有功能",[22,963,964,965],{},"包含",[276,966,967],{},"完整的 Vue 框架",[22,969,970],{},"支持多种构建格式（ESM、CJS、Global）",[22,972,964,973],{},[276,974,975],{},"编译器、服务端渲染等子包",[22,977,978],{},"runtime-core\u002F - 运行时核心",[22,980,981,982],{},"Vue 的",[276,983,984],{},"核心运行时逻辑",[22,986,987,988,991],{},"组件系统、响应式系统、",[276,989,990],{},"调度器","等",[993,994,995,1001],"blockquote",{},[15,996,997],{},[998,999,1000],"span",{},"!NOTE",[15,1002,1003],{},"这里调度器和组件系统等可以着重看一下",[45,1005,1006,1011,1014,1017,1020,1023,1026,1029],{},[22,1007,1008],{},[276,1009,1010],{},"平台无关的运行时实现",[22,1012,1013],{},"runtime-dom\u002F - DOM 运行时",[22,1015,1016],{},"浏览器环境的 DOM 操作",[22,1018,1019],{},"事件处理、属性绑定等",[22,1021,1022],{},"基于 runtime-core 的浏览器实现",[22,1024,1025],{},"runtime-test\u002F - 测试运行时",[22,1027,1028],{},"用于测试环境的运行时",[22,1030,1031],{},"提供测试工具和模拟环境",[768,1033,1035],{"id":1034},"_2-编译器包-compiler-packages","2. 编译器包 (Compiler Packages)",[45,1037,1038,1041,1044,1047,1053,1056,1062,1065,1068,1071,1074,1077,1080],{},[22,1039,1040],{},"compiler-core\u002F - 编译器核心",[22,1042,1043],{},"模板解析、AST 转换、代码生成",[22,1045,1046],{},"平台无关的编译逻辑",[22,1048,1049,1050],{},"支持",[276,1051,1052],{},"各种指令和语法",[22,1054,1055],{},"compiler-dom\u002F - DOM 编译器",[22,1057,1058,1059],{},"针对",[276,1060,1061],{},"浏览器环境的编译优化",[22,1063,1064],{},"DOM 特定的编译逻辑",[22,1066,1067],{},"compiler-ssr\u002F - SSR 编译器",[22,1069,1070],{},"服务端渲染的编译支持",[22,1072,1073],{},"静态优化和序列化",[22,1075,1076],{},"compiler-sfc\u002F - 单文件组件编译器",[22,1078,1079],{},".vue 文件的编译处理",[22,1081,1082],{},"模板、脚本、样式的分离和编译",[768,1084,1086],{"id":1085},"_3-响应式系统包","3. 响应式系统包",[45,1088,1089,1092,1098,1101],{},[22,1090,1091],{},"reactivity\u002F - 响应式系统",[22,1093,1094,1095],{},"Vue 3 的",[276,1096,1097],{},"响应式核心",[22,1099,1100],{},"reactive、ref、computed、watch 等 API",[22,1102,1103],{},"可独立使用的响应式库",[768,1105,1107],{"id":1106},"_4-服务端渲染包","4. 服务端渲染包",[45,1109,1110,1113,1116],{},[22,1111,1112],{},"server-renderer\u002F - 服务端渲染器",[22,1114,1115],{},"服务端渲染支持",[22,1117,1118,702,1121,991],{},[276,1119,1120],{},"流式渲染",[276,1122,1123],{},"序列化",[768,1125,1127],{"id":1126},"_5-兼容性包","5. 兼容性包",[45,1129,1130,1133,1139],{},[22,1131,1132],{},"vue-compat\u002F - Vue 2 兼容层",[22,1134,1135,1136],{},"提供 ",[276,1137,1138],{},"Vue 2 到 Vue 3 的迁移支持",[22,1140,1141],{},"兼容 Vue 2 的 API 和语法",[768,1143,1145],{"id":1144},"_6-共享工具包","6. 共享工具包",[45,1147,1148,1154,1159],{},[22,1149,1150,1151],{},"shared\u002F - ",[276,1152,1153],{},"共享工具",[22,1155,1156],{},[276,1157,1158],{},"各包之间共享的工具函数",[22,1160,1161],{},"类型定义、常量、工具函数等",[10,1163,1165],{"id":1164},"通用工具函数库shared","通用工具函数库：shared",[768,1167,1169],{"id":1168},"_1-indexts-入口文件","1. index.ts - 入口文件",[45,1171,1172,1175,1178],{},[22,1173,1174],{},"作用：了解整个共享工具库的结构",[22,1176,1177],{},"重点：理解各个模块的依赖关系",[22,1179,1180],{},"时间：15分钟",[768,1182,1184],{"id":1183},"_2-makemapts-映射表工具","2. makeMap.ts - 映射表工具",[45,1186,1187,1190,1193],{},[22,1188,1189],{},"作用：Vue 3 中最基础的工具函数",[22,1191,1192],{},"重点：理解性能优化策略（Object.create(null)、tree-shaking）",[22,1194,1195],{},"时间：30分钟",[1197,1198,1203],"pre",{"className":1199,"code":1200,"language":1201,"meta":1202,"style":1202},"language-ts shiki shiki-themes github-light github-dark","\u002F**\n * 创建映射表工具函数\n *\n * 该函数用于创建高效的字符串映射表，主要用于 Vue 3 中的各种配置检查，\n * 如 HTML 标签检查、SVG 标签检查、保留属性检查等。\n *\n * 性能优化：\n * - 使用 Object.create(null) 创建纯净对象，避免原型链查找\n * - 支持 tree-shaking，所有调用必须添加 PURE 注释\n * - 使用 in 操作符进行快速查找\n *\n * 使用示例：\n * ```typescript\n * const isHTMLTag = makeMap('div,span,p')\n * isHTMLTag('div') \u002F\u002F true\n * isHTMLTag('custom') \u002F\u002F false\n * ```\n *\u002F\n\n\u002F*@__NO_SIDE_EFFECTS__*\u002F\nexport function makeMap(str: string): (key: string) => boolean {\n  const map = Object.create(null)\n  \u002F\u002F 创建一个没有原型链的对象。避免了在使用 map[key] 或 key in map 时，JavaScript 引擎去查找 Object.prototype 上的继承属性（如 toString），从而加快查找速度。\n  \n  for (const key of str.split(',')) map[key] = 1\n    \u002F\u002F将列表转换为一个 Hash Map (哈希表)，查找时间复杂度接近 O(1)。比使用数组的 Array.prototype.includes() (O(N)) 快得多。赋值只需要一个简单的 1，比赋值 true 更简洁（尽管差异微小）。\n    \n  return val => val in map\n}\n\n\u002F*@__NO_SIDE_EFFECTS__*\u002F 的代码实现：\u002F*@__NO_SIDE_EFFECTS__*\u002F export function makeMap(...) \n    这是一个 Rollup\u002FWebpack 等打包工具识别的魔术注释（Magic Comment）。它告诉打包工具：调用这个函数没有副作用（Side Effect），如果该函数的返回值（即 isHTMLTag 检查器）在最终代码中没有被使用，那么整个 makeMap 函数以及它内部的逻辑都可以安全地被 Tree-Shaking 移除。  \n\n","ts","",[695,1204,1205,1213,1218,1223,1229,1234,1239,1244,1250,1256,1262,1267,1273,1279,1285,1294,1303,1309,1315,1322,1328,1383,1409,1415,1421,1459,1465,1471,1492,1498,1503,1524],{"__ignoreMap":1202},[998,1206,1209],{"class":1207,"line":1208},"line",1,[998,1210,1212],{"class":1211},"sJ8bj","\u002F**\n",[998,1214,1215],{"class":1207,"line":58},[998,1216,1217],{"class":1211}," * 创建映射表工具函数\n",[998,1219,1220],{"class":1207,"line":107},[998,1221,1222],{"class":1211}," *\n",[998,1224,1226],{"class":1207,"line":1225},4,[998,1227,1228],{"class":1211}," * 该函数用于创建高效的字符串映射表，主要用于 Vue 3 中的各种配置检查，\n",[998,1230,1231],{"class":1207,"line":177},[998,1232,1233],{"class":1211}," * 如 HTML 标签检查、SVG 标签检查、保留属性检查等。\n",[998,1235,1237],{"class":1207,"line":1236},6,[998,1238,1222],{"class":1211},[998,1240,1241],{"class":1207,"line":219},[998,1242,1243],{"class":1211}," * 性能优化：\n",[998,1245,1247],{"class":1207,"line":1246},8,[998,1248,1249],{"class":1211}," * - 使用 Object.create(null) 创建纯净对象，避免原型链查找\n",[998,1251,1253],{"class":1207,"line":1252},9,[998,1254,1255],{"class":1211}," * - 支持 tree-shaking，所有调用必须添加 PURE 注释\n",[998,1257,1259],{"class":1207,"line":1258},10,[998,1260,1261],{"class":1211}," * - 使用 in 操作符进行快速查找\n",[998,1263,1265],{"class":1207,"line":1264},11,[998,1266,1222],{"class":1211},[998,1268,1270],{"class":1207,"line":1269},12,[998,1271,1272],{"class":1211}," * 使用示例：\n",[998,1274,1276],{"class":1207,"line":1275},13,[998,1277,1278],{"class":1211}," * ```typescript\n",[998,1280,1282],{"class":1207,"line":1281},14,[998,1283,1284],{"class":1211}," * const isHTMLTag = makeMap('div,span,p')\n",[998,1286,1288,1291],{"class":1207,"line":1287},15,[998,1289,1290],{"class":1211}," * isHTMLTag('div')",[998,1292,1293],{"class":1211}," \u002F\u002F true\n",[998,1295,1297,1300],{"class":1207,"line":1296},16,[998,1298,1299],{"class":1211}," * isHTMLTag('custom')",[998,1301,1302],{"class":1211}," \u002F\u002F false\n",[998,1304,1306],{"class":1207,"line":1305},17,[998,1307,1308],{"class":1211}," * ```\n",[998,1310,1312],{"class":1207,"line":1311},18,[998,1313,1314],{"class":1211}," *\u002F\n",[998,1316,1318],{"class":1207,"line":1317},19,[998,1319,1321],{"emptyLinePlaceholder":1320},true,"\n",[998,1323,1325],{"class":1207,"line":1324},20,[998,1326,1327],{"class":1211},"\u002F*@__NO_SIDE_EFFECTS__*\u002F\n",[998,1329,1331,1334,1337,1341,1345,1349,1352,1356,1359,1361,1364,1367,1369,1371,1374,1377,1380],{"class":1207,"line":1330},21,[998,1332,846],{"class":1333},"szBVR",[998,1335,1336],{"class":1333}," function",[998,1338,1340],{"class":1339},"sScJk"," makeMap",[998,1342,1344],{"class":1343},"sVt8B","(",[998,1346,1348],{"class":1347},"s4XuR","str",[998,1350,1351],{"class":1333},":",[998,1353,1355],{"class":1354},"sj4cs"," string",[998,1357,1358],{"class":1343},")",[998,1360,1351],{"class":1333},[998,1362,1363],{"class":1343}," (",[998,1365,1366],{"class":1347},"key",[998,1368,1351],{"class":1333},[998,1370,1355],{"class":1354},[998,1372,1373],{"class":1343},") ",[998,1375,1376],{"class":1333},"=>",[998,1378,1379],{"class":1354}," boolean",[998,1381,1382],{"class":1343}," {\n",[998,1384,1386,1389,1392,1395,1398,1401,1403,1406],{"class":1207,"line":1385},22,[998,1387,1388],{"class":1333},"  const",[998,1390,1391],{"class":1354}," map",[998,1393,1394],{"class":1333}," =",[998,1396,1397],{"class":1343}," Object.",[998,1399,1400],{"class":1339},"create",[998,1402,1344],{"class":1343},[998,1404,1405],{"class":1354},"null",[998,1407,1408],{"class":1343},")\n",[998,1410,1412],{"class":1207,"line":1411},23,[998,1413,1414],{"class":1211},"  \u002F\u002F 创建一个没有原型链的对象。避免了在使用 map[key] 或 key in map 时，JavaScript 引擎去查找 Object.prototype 上的继承属性（如 toString），从而加快查找速度。\n",[998,1416,1418],{"class":1207,"line":1417},24,[998,1419,1420],{"class":1343},"  \n",[998,1422,1424,1427,1429,1432,1435,1438,1441,1444,1446,1450,1453,1456],{"class":1207,"line":1423},25,[998,1425,1426],{"class":1333},"  for",[998,1428,1363],{"class":1343},[998,1430,1431],{"class":1333},"const",[998,1433,1434],{"class":1354}," key",[998,1436,1437],{"class":1333}," of",[998,1439,1440],{"class":1343}," str.",[998,1442,1443],{"class":1339},"split",[998,1445,1344],{"class":1343},[998,1447,1449],{"class":1448},"sZZnC","','",[998,1451,1452],{"class":1343},")) map[key] ",[998,1454,1455],{"class":1333},"=",[998,1457,1458],{"class":1354}," 1\n",[998,1460,1462],{"class":1207,"line":1461},26,[998,1463,1464],{"class":1211},"    \u002F\u002F将列表转换为一个 Hash Map (哈希表)，查找时间复杂度接近 O(1)。比使用数组的 Array.prototype.includes() (O(N)) 快得多。赋值只需要一个简单的 1，比赋值 true 更简洁（尽管差异微小）。\n",[998,1466,1468],{"class":1207,"line":1467},27,[998,1469,1470],{"class":1343},"    \n",[998,1472,1474,1477,1480,1483,1486,1489],{"class":1207,"line":1473},28,[998,1475,1476],{"class":1333},"  return",[998,1478,1479],{"class":1347}," val",[998,1481,1482],{"class":1333}," =>",[998,1484,1485],{"class":1343}," val ",[998,1487,1488],{"class":1333},"in",[998,1490,1491],{"class":1343}," map\n",[998,1493,1495],{"class":1207,"line":1494},29,[998,1496,1497],{"class":1343},"}\n",[998,1499,1501],{"class":1207,"line":1500},30,[998,1502,1321],{"emptyLinePlaceholder":1320},[998,1504,1506,1509,1512,1514,1517,1519,1521],{"class":1207,"line":1505},31,[998,1507,1508],{"class":1211},"\u002F*@__NO_SIDE_EFFECTS__*\u002F",[998,1510,1511],{"class":1343}," 的代码实现：",[998,1513,1508],{"class":1211},[998,1515,1516],{"class":1333}," export",[998,1518,1336],{"class":1333},[998,1520,1340],{"class":1339},[998,1522,1523],{"class":1343},"(...) \n",[998,1525,1527,1530,1533,1535,1538,1541,1543,1546,1549,1551,1554,1557,1560,1562,1565,1568,1571,1574,1576,1579,1582,1585,1588,1591,1594,1597,1599,1602,1605,1608,1611,1614],{"class":1207,"line":1526},32,[998,1528,1529],{"class":1339},"    这是一个",[998,1531,1532],{"class":1339}," Rollup",[998,1534,282],{"class":1343},[998,1536,1537],{"class":1339},"Webpack",[998,1539,1540],{"class":1339}," 等打包工具识别的魔术注释",[998,1542,876],{"class":1343},[998,1544,1545],{"class":1339},"Magic",[998,1547,1548],{"class":1339}," Comment",[998,1550,863],{"class":1343},[998,1552,1553],{"class":1339},"它告诉打包工具",[998,1555,1556],{"class":1343},"：",[998,1558,1559],{"class":1339},"调用这个函数没有副作用",[998,1561,876],{"class":1343},[998,1563,1564],{"class":1339},"Side",[998,1566,1567],{"class":1339}," Effect",[998,1569,1570],{"class":1343},"），",[998,1572,1573],{"class":1339},"如果该函数的返回值",[998,1575,876],{"class":1343},[998,1577,1578],{"class":1339},"即",[998,1580,1581],{"class":1339}," isHTMLTag",[998,1583,1584],{"class":1339}," 检查器",[998,1586,1587],{"class":1343},"）",[998,1589,1590],{"class":1339},"在最终代码中没有被使用",[998,1592,1593],{"class":1343},"，",[998,1595,1596],{"class":1339},"那么整个",[998,1598,1340],{"class":1339},[998,1600,1601],{"class":1339}," 函数以及它内部的逻辑都可以安全地被",[998,1603,1604],{"class":1339}," Tree",[998,1606,1607],{"class":1343},"-",[998,1609,1610],{"class":1339},"Shaking",[998,1612,1613],{"class":1339}," 移除",[998,1615,811],{"class":1343},[15,1617,1618,1619,1622,1623,1625,1626,1629,1630,1632,1633,1635,1636,1638],{},"​\t这个用途是用于快速查找，是否一个字符串存在于一个预定定的列表之中，并做了很多的优化。",[695,1620,1621],{},"makeMap"," 接收一个用逗号分隔的字符串 (",[695,1624,1348],{},")，并返回一个",[276,1627,1628],{},"函数","。这个返回的函数接受一个字符串 ",[695,1631,1366],{},"，并判断这个 ",[695,1634,1366],{}," 是否包含在原始列表中。核心用途：配置和检查      在 Vue 3 源码中，",[695,1637,1621],{}," 被广泛用于创建各种配置检查器：",[19,1640,1641,1649,1657,1665],{},[22,1642,1643,727,1646],{},[276,1644,1645],{},"HTML 标签检查：",[695,1647,1648],{},"isHTMLTag = makeMap('div,span,a,p,...')",[22,1650,1651,727,1654],{},[276,1652,1653],{},"SVG 标签检查：",[695,1655,1656],{},"isSVGTag = makeMap('svg,path,g,...')",[22,1658,1659,727,1662],{},[276,1660,1661],{},"保留属性检查：",[695,1663,1664],{},"isReservedProp = makeMap('key,ref,v-model,...')",[22,1666,1667,727,1670],{},[276,1668,1669],{},"事件属性检查：",[695,1671,1672],{},"isOn = makeMap('onUpdate,onClick,...')",[15,1674,1675],{},"通过这种方式，Vue 可以在编译或运行时快速判断一个标签名或属性名是否有效、是否需要特殊处理。",[768,1677,1679],{"id":1678},"_3-generalts-通用工具函数","3. general.ts - 通用工具函数",[45,1681,1682,1685,1688],{},[22,1683,1684],{},"作用：最常用的工具函数集合",[22,1686,1687],{},"重点：类型检查、字符串处理、对象操作",[22,1689,1690],{},"时间：1-2小时",[424,1692,1694],{"id":1693},"第二阶段核心算法-2-3天","第二阶段：核心算法 (2-3天)",[768,1696,1698],{"id":1697},"_4-looseequalts-宽松比较","4. looseEqual.ts - 宽松比较",[45,1700,1701,1704,1707],{},[22,1702,1703],{},"作用：响应式系统的核心算法",[22,1705,1706],{},"重点：递归比较、类型处理、性能优化",[22,1708,1709],{},"时间：1小时",[768,1711,1713],{"id":1712},"_5-todisplaystringts-显示字符串转换","5. toDisplayString.ts - 显示字符串转换",[45,1715,1716,1719,1722],{},[22,1717,1718],{},"作用：模板插值的核心功能",[22,1720,1721],{},"重点：各种数据类型的转换逻辑",[22,1723,1724],{},"时间：45分钟",[768,1726,1728],{"id":1727},"_6-escapehtmlts-html-转义","6. escapeHtml.ts - HTML 转义",[45,1730,1731,1734,1737],{},[22,1732,1733],{},"作用：安全防护机制",[22,1735,1736],{},"重点：XSS 防护、字符转义算法",[22,1738,1195],{},[424,1740,1742],{"id":1741},"第三阶段标志位系统-1-2天","第三阶段：标志位系统 (1-2天)",[768,1744,1746],{"id":1745},"_7-shapeflagsts-形状标志位","7. shapeFlags.ts - 形状标志位",[45,1748,1749,1752,1755],{},[22,1750,1751],{},"作用：虚拟节点类型标识",[22,1753,1754],{},"重点：位运算、节点类型判断",[22,1756,1195],{},[768,1758,1760],{"id":1759},"_8-patchflagsts-补丁标志位","8. patchFlags.ts - 补丁标志位",[45,1762,1763,1766,1769],{},[22,1764,1765],{},"作用：Vue 3 性能优化的核心",[22,1767,1768],{},"重点：位运算、优化策略、编译器提示",[22,1770,1690],{},[768,1772,1774],{"id":1773},"_9-slotflagsts-插槽标志位","9. slotFlags.ts - 插槽标志位",[45,1776,1777,1780,1783],{},[22,1778,1779],{},"作用：插槽优化策略",[22,1781,1782],{},"重点：插槽稳定性、更新策略",[22,1784,1195],{},[424,1786,1788],{"id":1787},"第四阶段属性处理-1-2天","第四阶段：属性处理 (1-2天)",[768,1790,1792],{"id":1791},"_10-normalizepropts-属性标准化","10. normalizeProp.ts - 属性标准化",[45,1794,1795,1798,1801],{},[22,1796,1797],{},"作用：处理 class 和 style 属性",[22,1799,1800],{},"重点：样式解析、属性合并算法",[22,1802,1709],{},[768,1804,1806],{"id":1805},"_11-cssvarsts-css-变量处理","11. cssVars.ts - CSS 变量处理",[45,1808,1809,1812,1815],{},[22,1810,1811],{},"作用：CSS-in-JS 功能支持",[22,1813,1814],{},"重点：CSS 变量标准化、类型检查",[22,1816,1195],{},[424,1818,1820],{"id":1819},"第五阶段dom-相关-1-2天","第五阶段：DOM 相关 (1-2天)",[768,1822,1824],{"id":1823},"_12-domtagconfigts-dom-标签配置","12. domTagConfig.ts - DOM 标签配置",[45,1826,1827,1830,1833],{},[22,1828,1829],{},"作用：HTML\u002FSVG\u002FMathML 标签识别",[22,1831,1832],{},"重点：标签分类、性能优化",[22,1834,1724],{},[768,1836,1838],{"id":1837},"_13-domattrconfigts-dom-属性配置","13. domAttrConfig.ts - DOM 属性配置",[45,1840,1841,1844,1847],{},[22,1842,1843],{},"作用：属性处理和安全检查",[22,1845,1846],{},"重点：属性映射、安全检查",[22,1848,1709],{},[424,1850,1852],{"id":1851},"第六阶段高级工具-1天","第六阶段：高级工具 (1天)",[768,1854,1856],{"id":1855},"_14-typeutilsts-typescript-类型工具","14. typeUtils.ts - TypeScript 类型工具",[45,1858,1859,1862,1865],{},[22,1860,1861],{},"作用：类型系统增强",[22,1863,1864],{},"重点：高级类型、类型推导",[22,1866,1709],{},[768,1868,1870],{"id":1869},"_15-globalsallowlistts-全局变量白名单","15. globalsAllowList.ts - 全局变量白名单",[45,1872,1873,1876,1879],{},[22,1874,1875],{},"作用：模板安全机制",[22,1877,1878],{},"重点：安全策略、全局变量控制",[22,1880,1195],{},[768,1882,1884],{"id":1883},"_16-codeframets-代码框架生成","16. codeframe.ts - 代码框架生成",[45,1886,1887,1890,1893],{},[22,1888,1889],{},"作用：错误定位工具",[22,1891,1892],{},"重点：字符串处理、错误显示",[22,1894,1724],{},[765,1896,1897],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":1202,"searchDepth":58,"depth":58,"links":1899},[1900,1901,1902,1907],{"id":12,"depth":58,"text":13},{"id":371,"depth":58,"text":372},{"id":401,"depth":58,"text":402,"children":1903},[1904,1905,1906],{"id":426,"depth":107,"text":426},{"id":620,"depth":107,"text":621},{"id":951,"depth":107,"text":952},{"id":1164,"depth":58,"text":1165,"children":1908},[1909,1910,1911,1912,1913],{"id":1693,"depth":107,"text":1694},{"id":1741,"depth":107,"text":1742},{"id":1787,"depth":107,"text":1788},{"id":1819,"depth":107,"text":1820},{"id":1851,"depth":107,"text":1852},"md",{},"\u002Fvue\u002Fvue源码解读笔记共享工具库",{"description":1202},"Vue\u002Fvue源码解读笔记共享工具库","lyM03WRuLjXPEioXVptsIt4wchRx16hQcUIRI5I7Vho",1791042470940]