当前位置: 首页 > article >正文

Vue 3 源码层核心原理剖析(完整详解版)

一、Compiler 编译过程解密:多框架实现对比

Vue 3 编译流程深度解析(基于 /packages/compiler-core/src/parse.ts

完整编译链条及技术实现

模板字符串
词法分析
Tokenizer
生成Token流
Token Stream
语法解析
Parser
构建AST
Abstract Syntax Tree
语义分析
Semantic Analysis
优化标记
Optimization
代码生成
CodeGen

01、词法分析阶段(Tokenizer)

1. 核心实现机制

Vue 3 编译器采用**有限状态机(Finite State Machine, FSM)**解析模板字符串,核心逻辑位于/packages/compiler-core/src/parse.tsparse函数:

// 解析器入口函数
function parse(content: string, options: ParserOptions = {}): RootNode {// 创建解析上下文const context = createParserContext(content, options)// 获取初始光标位置const start = getCursor(context)// 解析子节点(核心处理逻辑)const children = parseChildren(context, [])// 返回AST根节点return {type: NodeTypes.ROOT,children,loc: getSelection(context, start), // 记录源码位置信息components: [],                    // 组件集合directives: [],                    // 指令集合hoists: [],                        // 静态提升节点imports: [],                       // 导入声明cached: 0,                         // 缓存节点计数temps: 0                           // 临时变量计数}
}
2. 核心正则表达式

Vue 使用以下正则表达式进行词法分析,识别模板中的关键元素:

// 标准标签名(字母/下划线开头,可包含连字符、点、数字)
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`// 带命名空间的标签(如<svg:circle>)
const qnameCapture = `((?:${ncname}\\:)?${ncname})`// 开始标签匹配(如<div>)
const startTagOpen = new RegExp(`^<${qnameCapture}`)// 开始标签结束(匹配>或/>)
const startTagClose = /^\s*(\/?)>/// 属性解析(识别属性名、等号、属性值)
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/// 结束标签匹配(如</div>)
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)// 文档类型声明(<!DOCTYPE>)
const doctype = /^<!DOCTYPE [^>]+>/i// 注释节点(<!-- comment -->)
const comment = /^<!\--/// 条件注释(<![if IE]>)
const conditionalComment = /^<!\[/
3. 词法分析处理流程

状态机按以下顺序处理模板内容:

  1. 标签开闭识别

    // 处理开始标签
    if (startTagOpen.test(html)) {const startTagMatch = parseStartTag()if (startTagMatch) {handleStartTag(startTagMatch)continue}
    }// 处理结束标签
    if (endTag.test(html)) {const endTagMatch = html.match(endTag)if (endTagMatch) {advance(endTagMatch[0].length)parseEndTag(endTagMatch[1])continue}
    }
    
  2. 属性解析

    while (!end(html) &&!(endTag.test(html)) &&!(startTagOpen.test(html)) &&(attr = html.match(attribute))
    ) {advance(attr[0].length)match.attrs.push(attr)
    }
    
  3. 文本插值处理 ({{ value }})

    if (html.indexOf(context.options.delimiters[0]) === 0) {// 解析插值表达式const [full, content] = parseInterpolation(context)nodes.push({type: NodeTypes.INTERPOLATION,content: {type: NodeTypes.SIMPLE_EXPRESSION,content,isStatic: false,constType: ConstantTypes.NOT_CONSTANT},loc: getSelection(context, start)})
    }
    
  4. 指令识别 (v-if, v-for等)

    if (/^(v-[A-Za-z0-9-]|:|\.|@|#)/.test(name)) {// 解析指令const match = /(?:^v-([a-z0-9-]+))?(?:(?::|\.|@|#)(\[[^\]]+\]|[^\.]+))?(.+)?$/i.exec(name)if (match) {// 提取指令名、参数、修饰符const dirName = match[1] || (startsWith(name, ':') ? 'bind' : ''const arg = match[2] ? match[2].trim() : undefined// 构建指令节点addDirective(node, dirName, arg, modifiers)}
    }
    
  5. 特殊符号处理

    // 处理<!DOCTYPE>
    if (doctype.test(html)) {advance(html.match(doctype)[0].length)continue
    }// 处理注释节点
    if (comment.test(html)) {const commentEnd = html.indexOf('-->')if (commentEnd >= 0) {advance(commentEnd + 3)continue}
    }// 处理条件注释
    if (conditionalComment.test(html)) {const conditionalEnd = html.indexOf(']>')if (conditionalEnd >= 0) {advance(conditionalEnd + 2)continue}
    }
    
4. 状态机工作流程

词法分析的状态转换流程如下:

遇到 '<'
遇到 '{{'
其他字符
开始标签
继续收集属性
遇到 '>' 或 '/>'
非 '}}' 字符
遇到 '}}'
非 '<' 非 '{{'
遇到 '<' 或 '{{'
初始状态
检测符号
标签状态
插值状态
文本状态
属性收集
标签结束
5. 错误处理机制

状态机包含完善的错误检测:

// 标签嵌套检查
function parseChildren(context, ancestors) {const parent = last(ancestors)while (!isEnd(context, ancestors)) {// ...解析逻辑...}// 检查未闭合标签if (parent && context.source) {emitError(context,ErrorCodes.X_MISSING_END_TAG,parent.loc.start)}
}// 自定义错误类型
export const enum ErrorCodes {X_MISSING_END_TAG = 1,        // 缺少结束标签X_MISSING_INTERPOLATION_END,  // 缺少插值结束符号X_MISSING_DIRECTIVE_NAME,     // 指令名缺失X_MISSING_ATTRIBUTE_VALUE,    // 属性值缺失X_INVALID_DIRECTIVE_ARG,      // 无效的指令参数// ...20+种错误类型...
}
6. 位置信息追踪

编译器精确记录每个节点的源码位置:

// 获取当前光标位置
function getCursor(context: ParserContext): Position {const { column, line, offset } = contextreturn { column, line, offset }
}// 记录节点位置范围
function getSelection(context: ParserContext,start: Position,end?: Position
): SourceLocation {return {start,end: end || getCursor(context),source: context.originalSource.slice(start.offset, context.offset)}
}
7. 性能优化策略
  1. 增量解析:使用advance()逐步消费模板字符串

    function advance(context: ParserContext, numberOfChars: number) {const { source } = context// 更新行列计数advancePositionWithMutation(context, source, numberOfChars)// 截取剩余字符串context.source = source.slice(numberOfChars)
    }
    
  2. 预扫描优化:快速跳过大型文本节点

    if (textEnd > 0) {// 批量处理文本内容const text = context.source.slice(0, textEnd)advance(context, textEnd)return text
    }
    
  3. 正则表达式优化:所有正则使用^开头锚点确保高效匹配

这种基于有限状态机的词法分析设计,使Vue 3编译器能在O(n)时间复杂度内完成模板解析,同时保持精确的错误定位能力,为后续的语法解析和优化阶段奠定坚实基础。

02、语法解析阶段(Parser)

使用递归下降算法构建AST,核心逻辑:

function parseChildren(context: ParserContext, ancestors: ElementNode[]): TemplateChildNode[] {const nodes: TemplateChildNode[] = []while (!isEnd(context, ancestors)) {const s = context.sourcelet node: TemplateChildNode | undefinedif (startsWith(s, context.options.delimiters[0])) {// 解析插值表达式 {{ value }}node = parseInterpolation(context)} else if (s[0] === '<') {// 解析元素标签if (/[a-z]/i.test(s[1])) {node = parseElement(context, ancestors)}}if (!node) {// 解析纯文本内容node = parseText(context)}pushNode(nodes, node)}return nodes
}

03、语义优化技术

Vue 3特有的编译时优化:

  • 静态节点提升(hoistStatic):将静态节点提取到渲染函数外部,避免重复创建
// 优化前
function render() {return h('div', [h('span', '静态内容'),h('p', dynamicValue)])
}// 优化后
const _hoisted = h('span', '静态内容')
function render() {return h('div', [_hoisted,h('p', dynamicValue)])
}
  • 补丁标志(patchFlag):使用位运算标记动态节点类型
// patchFlags 位掩码定义
export const enum PatchFlags {TEXT = 1,          // 动态文本内容CLASS = 1 << 1,    // 动态class绑定STYLE = 1 << 2,    // 动态style绑定PROPS = 1 << 3,    // 动态非class/style属性FULL_PROPS = 1 << 4, // 需要完整props比较HYDRATE_EVENTS = 1 << 5, // 带事件监听器STABLE_FRAGMENT = 1 << 6, // 稳定片段(子节点顺序不变)KEYED_FRAGMENT = 1 << 7, // 带key的片段UNKEYED_FRAGMENT = 1 << 8, // 无key的片段NEED_PATCH = 1 << 9, // 需要非props补丁DYNAMIC_SLOTS = 1 << 10 // 动态插槽
}
  • 缓存事件处理程序(cacheHandler):避免重复创建事件处理器
// 优化前
function render() {return h('button', { onClick: () => handler() })
}// 优化后
const _cache = {}
function render() {return h('button', { onClick: _cache[1] || (_cache[1] = () => handler())})
}

Vue 2 编译实现深度对比

架构级差异

基于正则的解析器
递归遍历
状态机解析器
优化遍历
Vue 2
AST生成
渲染函数生成
Vue 3
AST生成
增强渲染函数

1. 解析器实现差异
Vue 2 使用基于正则的字符串处理(/src/compiler/parser/index.js):

// Vue 2 解析器核心
parseHTML(template, {start(tag, attrs, unary) {// 处理开始标签const element = createASTElement(tag, attrs)processElement(element)},end() {// 处理结束标签closeElement()},chars(text) {// 处理文本内容handleText(text)},comment(text) {// 处理注释handleComment(text)}
})

Vue 3 使用状态机驱动的位运算(/packages/compiler-core/src/parse.ts):

// 文本解析模式状态枚举
const enum TextModes {DATA,           // 默认模式RCDATA,         // <textarea> 内容模式RAWTEXT,        // <style>,<script> 模式CDATA,          // <![CDATA[ 内容ATTRIBUTE_VALUE // 属性值解析模式
}// 状态转换逻辑
function parseTag(context: ParserContext, type: TagType): ElementNode {const start = getCursor(context)const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source)!const tag = match[1]advanceBy(context, match[0].length)advanceSpaces(context)// 属性解析状态处理const props = parseAttributes(context, type)// 其他状态处理...
}

2. AST结构差异
Vue 2 AST节点(简化):平铺式节点结构

{type: 1, // 元素节点tag: 'div',attrsList: [{ name: 'class', value: 'container' }],children: [{ type: 2, text: '{{ message }}', expression: '_s(message)' }]
}

Vue 3 AST节点(增强):树形结构+动态标记

interface ElementNode extends Node {type: NodeTypes.ELEMENTtag: stringtagType: ElementTypesprops: Array<AttributeNode | DirectiveNode>children: TemplateChildNode[]codegenNode: CodegenNode | undefined// 新增优化字段patchFlag: numberdynamicProps: string[] | nullisStatic: boolean
}
React JSX 编译原理详解

Babel 转换流程

// JSX 源代码
<div className="container" onClick={handleClick}>{message}<Button>提交</Button>
</div>// 经babel转换后(React 16)
React.createElement("div",{ className: "container", onClick: handleClick },message,React.createElement(Button, null, "提交")
)

编译时优化

// React 17+ 新转换
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
_jsxs("div", {className: "container",onClick: handleClick,children: [message,_jsx(Button, { children: "提交" })]
});

与Vue的核心差异

  1. 无静态提升:每次渲染都创建完整的VNode树
  2. 无补丁标志:依赖Virtual DOM的全量diff
  3. 无编译时优化:JSX直接转换为运行时函数调用
  4. 动态处理:所有优化在运行时完成(如React.memo)

编译时优化尝试

// React Forget编译器(实验性)
function Component(props) {"use no forget"const [count, setCount] = useState(0)const doubled = count * 2 // 自动记忆化return <div>{doubled}</div>
}

二、响应式系统实现:多框架深度对比

Vue 3 响应式系统(Proxy实现)

核心架构

reactive
Proxy代理
get拦截器
track依赖收集
set拦截器
trigger触发更新
调度器scheduler
批量更新

生产级实现细节

// 响应式入口(/packages/reactivity/src/reactive.ts)
function reactive(target: object) {// 避免重复代理if (target[ReactiveFlags.RAW] && !(isReadonly && target[ReactiveFlags.IS_REACTIVE])) {return target}// 查找现有代理const existingProxy = proxyMap.get(target)if (existingProxy) return existingProxy// 创建代理const proxy = new Proxy(target,baseHandlers)proxyMap.set(target, proxy)return proxy
}// 数组方法重写(/packages/reactivity/src/baseHandlers.ts)
const arrayInstrumentations: Record<string, Function> = {}
;['push', 'pop', 'shift', 'unshift', 'splice'].forEach(key => {arrayInstrumentations[key] = function (...args: any[]) {pauseTracking() // 暂停依赖收集const res = (this as any)[key].apply(this, args)resetTracking() // 恢复依赖收集return res}
})

依赖收集系统

// 依赖收集器(/packages/reactivity/src/effect.ts)
class ReactiveEffect {deps: Dep[] = [] // 依赖此effect的所有deprun() {try {this.parent = activeEffectactiveEffect = thisshouldTrack = true// 执行前清空依赖cleanupEffect(this)// 执行副作用函数return this.fn()} finally {activeEffect = this.parentshouldTrack = lastShouldTrackthis.parent = undefined}}
}// 依赖收集(track函数)
function track(target: object, type: TrackOpTypes, key: unknown) {if (!shouldTrack || activeEffect === undefined) returnlet depsMap = targetMap.get(target)if (!depsMap) {targetMap.set(target, (depsMap = new Map()))}let dep = depsMap.get(key)if (!dep) {depsMap.set(key, (dep = createDep()))}trackEffects(dep)
}function trackEffects(dep: Dep) {if (!activeEffect) return// 建立双向依赖关系dep.add(activeEffect)activeEffect.deps.push(dep)
}

生产级优化
1.嵌套代理缓存
2.数组方法拦截
3.调度器批量更新

Vue 2 响应式系统深度解析

实现原理

// 响应式入口(/src/core/observer/index.js)
class Observer {constructor(value) {this.value = valuethis.dep = new Dep()def(value, '__ob__', this)if (Array.isArray(value)) {// 数组响应式处理augment(value, arrayMethods, arrayKeys)this.observeArray(value)} else {// 对象响应式处理this.walk(value)}}walk(obj) {const keys = Object.keys(obj)for (let i = 0; i < keys.length; i++) {defineReactive(obj, keys[i])}}
}// 属性劫持
function defineReactive(obj, key, val) {const dep = new Dep()// 处理嵌套对象let childOb = observe(val)Object.defineProperty(obj, key, {enumerable: true,configurable: true,get: function reactiveGetter() {const value = valif (Dep.target) {dep.depend() // 收集依赖if (childOb) {childOb.dep.depend() // 嵌套对象依赖收集if (Array.isArray(value)) {dependArray(value) // 数组依赖收集}}}return value},set: function reactiveSetter(newVal) {if (newVal === value) returnval = newValchildOb = observe(newVal) // 新值响应式处理dep.notify() // 触发更新}})
}

局限性解决方案

// Vue.set 实现(/src/core/observer/index.js)
function set(target, key, val) {// 处理数组if (Array.isArray(target) {target.length = Math.max(target.length, key)target.splice(key, 1, val)return val}// 处理对象if (hasOwn(target, key)) {target[key] = valreturn val}// 新增属性const ob = target.__ob__if (!ob) {target[key] = valreturn val}// 将新属性转为响应式defineReactive(ob.value, key, val)ob.dep.notify() // 手动触发更新return val
}

局限性对比

特性Vue2Vue3
属性增删检测❌ 需Vue.set原生支持
数组索引变更❌需重写方法原生支持
性能开销O(n) 属性级劫持O(1) 对象级代理

React 响应式系统原理

Hooks 实现机制

// useState 简化实现(模拟 React 源码)
let hookStates = []
let hookIndex = 0
let scheduleUpdate = nullfunction useState(initialState) {const currentIndex = hookIndexhookStates[currentIndex] = hookStates[currentIndex] || (typeof initialState === 'function' ? initialState() : initialState)const setState = (newState) => {// 状态对比(使用 Object.is)if (Object.is(hookStates[currentIndex], newState)) return// 处理函数式更新hookStates[currentIndex] = typeof newState === 'function' ? newState(hookStates[currentIndex]) : newState// 触发重新渲染scheduleUpdate()}hookIndex++return [hookStates[currentIndex], setState]
}// useEffect 简化实现
function useEffect(callback, deps) {const currentIndex = hookIndexconst [lastDeps, cleanup] = hookStates[currentIndex] || [null, null]// 依赖比较const hasChanged = !deps || !lastDeps || deps.some((dep, i) => !Object.is(dep, lastDeps[i]))if (hasChanged) {// 执行清理函数if (cleanup && typeof cleanup === 'function') cleanup()// 异步执行effectPromise.resolve().then(() => {const cleanupFn = callback()hookStates[currentIndex] = [deps, cleanupFn]})}hookIndex++
}

更新机制对比

特性Vue 3React
更新粒度组件内元素级组件级
依赖跟踪自动手动(依赖数组)
状态变更检测Proxy 拦截Object.is 比较
批量更新自动(nextTick)自动(事件处理中)
异步更新队列
嵌套更新处理自动防止无限循环最大更新深度限制

Vue:自动依赖追踪,精确更新

React:组件树重渲染+差异比对

优化策略:

Vue:响应式依赖追踪

React:memo/shouldComponentUpdate

三、跨框架编译优化策略对比

优化策略Vue 3Vue 2React
静态提升✅ 提取静态节点到渲染函数外部❌ 无❌ 无
补丁标志✅ 位运算标记动态元素 (PatchFlags)❌ 无❌ 无
事件缓存✅ 自动缓存事件处理器❌ 无❌ 无
树结构优化✅ Block Tree 减少动态节点遍历❌ 递归全量diff✅ Fiber架构增量渲染
常量折叠✅ 编译时计算静态表达式⚠️ 有限支持❌ 无
按需更新✅ 元素级精确更新⚠️ 组件级⚠️ 组件级
SSR优化✅ 同构hydration + 静态内容直出⚠️ 基础SSR支持✅ Streaming SSR + Suspense
代码拆分✅ 基于路由的异步组件⚠️ 异步组件✅ React.lazy + Suspense
Tree Shaking✅ 良好支持⚠️ 有限支持✅ 完善支持
源映射支持✅ 完整模板到渲染函数的source map⚠️ 部分支持✅ JSX到JS的source map

四、编译与响应式协同工作原理

Vue 3 运行时完整工作流

模板 编译器 响应式系统 渲染器 DOM 原始模板字符串 解析优化 (AST生成) 生成render函数 建立响应式绑定 数据变更 trigger触发 执行render函数 生成vnode树 diff算法比对 最小化DOM操作 loop [响应式更新循环] 模板 编译器 响应式系统 渲染器 DOM

协同优势详解

  1. 编译时信息利用

    • 编译器识别静态节点,减少运行时比较
    • 补丁标志指导运行时diff算法优化路径
    // 基于patchFlag的优化diff
    if (patchFlag & PatchFlags.CLASS) {// 只需更新classupdateClass(oldVNode, newVNode)
    } else if (patchFlag & PatchFlags.STYLE) {// 只需更新styleupdateStyle(oldVNode, newVNode)
    } else if (patchFlag & PatchFlags.TEXT) {// 只需更新文本内容updateText(oldVNode, newVNode)
    }
    
  2. 响应式精准更新

    • 依赖收集系统建立数据与视图的精确关联
    • 避免不必要的组件重新渲染
    // 组件更新条件(/packages/runtime-core/src/componentRenderUtils.ts)
    shouldUpdateComponent(prevVNode: VNode,nextVNode: VNode,optimized?: boolean
    ): boolean {// 通过patchFlag快速判断if (nextVNode.patchFlag > 0) {const flag = nextVNode.patchFlagif (flag & PatchFlags.DYNAMIC_SLOTS) {return true}if (flag & PatchFlags.FULL_PROPS) {// 需要完整props比较} else {// 仅检查特定props}}
    }
    
  3. 内存优化策略

    • 静态节点提升减少内存分配
    • 事件缓存减少函数对象创建
    • 组件实例复用策略

五、框架设计哲学对比

设计维度Vue 3React
核心思想渐进增强 + 编译优化函数式编程 + 不可变数据
更新机制自动依赖追踪 + 精准更新状态驱动 + 虚拟DOM diff
模板系统声明式模板 + 指令系统JSX(JavaScript 语法扩展)
状态管理响应式自动依赖收集手动状态管理 + 依赖数组
学习曲线模板导向,较低门槛JSX导向,较高抽象能力要求
性能策略编译时优化为主 + 运行时辅助运行时优化为主
类型支持TypeScript 优先TypeScript 完善支持
移动端支持Weex/NativeScriptReact Native
未来方向Vapor模式(更细粒度响应式)React Forget(编译优化)
SSR架构Nuxt.js + ViteNext.js + React Server Components

六、源码学习指南

Vue 3 核心源码路径

  1. 编译器入口/packages/compiler-core/src/compile.ts

    • baseCompile 函数:完整编译流程入口
    • transform 模块:AST转换优化核心
  2. 解析器实现/packages/compiler-core/src/parse.ts

    • baseParse 函数:模板解析入口
    • parseElement:元素节点解析逻辑
    • parseInterpolation:插值表达式解析
  3. 响应式系统/packages/reactivity/src/

    • reactive.ts:响应式入口
    • effect.ts:副作用管理核心
    • baseHandlers.ts:Proxy处理器实现
    • collectionHandlers.ts:集合类型处理器
  4. 运行时核心/packages/runtime-core/src/

    • renderer.ts:渲染器实现
    • componentRenderUtils.ts:组件渲染工具
    • scheduler.ts:异步调度队列

React 核心源码路径

  1. 调和器/packages/react-reconciler/src/

    • ReactFiberWorkLoop.js:Fiber调度核心
    • ReactFiberBeginWork.js:Fiber节点处理
    • ReactFiberCompleteWork.js:Fiber完成工作
  2. Hooks系统/packages/react/src/

    • ReactHooks.js:Hook入口
    • Hooks.js:Hook实现核心
  3. JSX运行时/packages/react/src/jsx/

    • ReactJSX.js:JSX元素创建
    • ReactJSXElementValidator.js:JSX元素验证

对比学习建议

  1. 编译器设计对比

    • Vue 的 transformElement vs Babel 的 transform-react-jsx
    • Vue 的 AST 优化遍历 vs React 的运行时优化
  2. 响应式实现对比

    • Vue 的 track/targetMap 依赖收集 vs React 的 useState/useEffect 依赖数组
    • Vue 的响应式更新调度 vs React 的 Fiber 调度算法
  3. 渲染优化对比

    • Vue 的 Block Tree 机制 vs React 的 Fiber 树
    • Vue 的静态节点提升 vs React 的 React.memo

性能优化本质差异
Vue:通过编译获取模板语义信息,在运行时做最少的工作
React:通过虚拟DOM和差异比对,在运行时做智能的更新决策

调试技巧

  1. 使用 Vue 的 @vue/compiler-sfc 单独测试编译输出
  2. 使用 React 的 __PROFILE__ 标记进行性能分析
  3. 通过源码映射(sourcemap)在浏览器调试原始代码

总结:现代框架演进趋势

  1. 编译与运行时的深度融合

    • Vue:Vapor 模式(实验性)将更多逻辑移至编译时
    // Vapor 模式示例(概念)
    const __vapor__ = compile(`<div>{{ msg }}</div>`)
    function setup() {const msg = ref('Hello')return __vapor__({ msg })
    }
    
    • React:React Forget 编译器自动记忆化
    • Svelte:激进编译策略生成极简运行时
  2. 响应式范式的统一

    • Vue:保持基于 Proxy 的响应式
    • React:探索 Signal 基础原语
    // React Signals 提案(实验性)
    const count = createSignal(0)
    const double = createMemo(() => count.value * 2)
    return <div>{double.value}</div>
    
  3. 全栈架构的整合

    • Vue:Vite + SSR + Pinia 一体化
    • React:Next.js + Server Components + Turbopack
    • 共同点:服务端组件、岛屿架构(Islands Architecture)
  4. 类型系统的演进

    • Vue:<script setup> + TypeScript + Volar
    • React:TypeScript 优先 + 更严格的类型检查
    • 共同点:提升大型应用可维护性
  5. 性能基准的持续优化

    • Vue:优化内存占用(静态提升)
    • React:优化交互响应(并发渲染)
    • 共同目标:达到接近原生性能的Web体验

码字不易,各位大佬点点赞呗

相关文章:

Vue 3 源码层核心原理剖析(完整详解版)

一、Compiler 编译过程解密&#xff1a;多框架实现对比 Vue 3 编译流程深度解析&#xff08;基于 /packages/compiler-core/src/parse.ts&#xff09; 完整编译链条及技术实现&#xff1a; #mermaid-svg-S8ScpxdjkcJv0YWT {font-family:"trebuchet ms",verdana,ari…...

数据库操作-MySQL-4(JDBC编程)

JDBC&#xff1a;通过Java代码操作mysql数据库&#xff0c;数据库会提供一些API供我们调用 MySQL、Oracle、等API有差异&#xff0c;但是Java统一了所有接口&#xff0c;即JDBC&#xff1b; 原始api-驱动包&#xff08;类似转接头&#xff09;-统一的api-Java 驱动包&#xff1…...

Linux打开.img镜像文件

kparkx 可以查看和修改img文件的内容 1.安装kparkx 1.安装 kpartx sudo apt-get update sudo apt-get install kpartx2.使用kpartx映射镜像文件 假设镜像文件名为 example.img &#xff0c;以下命令会将其分区映射到 dev/mapper/ sudo kpartx -av example.img• -a表示添加…...

【FAQ】HarmonyOS SDK 闭源开放能力 —Account Kit(5)

1.问题描述&#xff1a; 集成华为一键登录的LoginWithHuaweiIDButton&#xff0c; 但是Button默认名字叫 “华为账号一键登录”&#xff0c;太长无法显示&#xff0c;能否简写成“一键登录”与其他端一致&#xff1f; 解决方案&#xff1a; 问题分两个场景&#xff1a; 一、…...

【科研绘图系列】R语言绘制论文组合图形(multiple plots)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理画图1画图2画图3画图4画图5系统信息介绍 这篇文章详细介绍了如何使用R语言进行科研绘图,特别是绘制论文组合图形(multiple plots)。文章从数…...

springMVC-9数据格式化

数据格式化 学习目标&#xff1a; 理解在我们提交数据(比如表单时)&#xff0c;SpringMVC怎样对提交的数据进行转换和处理的 Spring MVC 上下文中内建了很多转换器&#xff0c;可完成大多数 Java 类型的转换工作。 基本数据类型可以和字符串之间自动完成转换 应用实例-页面…...

Kafka 和Redis 在系统架构中的位置

Kafka 位置&#xff1a;位于应用层和数据存储层之间&#xff0c;作为消息队列和数据传输中间件。作用&#xff1a; 数据收集与传输&#xff1a;收集应用层产生的数据&#xff0c;传输到后端数据存储系统。消息队列&#xff1a;实现应用层各服务之间的异步通信和解耦。与应用层…...

【Spring AI】如何实现文生图功能

在人工智能与软件开发深度融合的当下&#xff0c;Spring AI 作为构建 AI 驱动应用的有力框架&#xff0c;能够便捷集成各类 AI 能力。 文生图技术可将文本描述转化为图像&#xff0c;极具应用价值。接下来&#xff0c;我给大家详细讲解一下如何使用 Spring AI 调用文生图功能。…...

【ISAQB大纲解读】Kafka消息总线被视为“自下而上设计”?

Kafka消息总线被视为“自下而上设计”的典型案例&#xff0c;核心在于其设计路径和演化逻辑完全符合自下而上方法的本质特征&#xff1a; 自下而上设计的核心逻辑 #mermaid-svg-pDSqW0S2h0bj15iN {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16…...

ISBN书号查询接口如何用PHP实现调用?

一、什么是ISBN书号查询接口 ISBN数据查询接口是一项图书信息查询服务。它基于全球通用的ISBN编码系统&#xff0c;帮助用户快速获取图书的详细信息&#xff0c;包括书名、作者、出版社、出版时间、价格、封面等关键字段。 该接口广泛应用于电商平台、图书馆管理系统、二手书…...

什么是 Docker Compose 的网络(network),为什么你需要它,它是怎么工作的

Docker Compose 的网络就是&#xff1a;让多个容器之间能像“连上同一个局域网”一样互相通信&#xff0c;不用管 IP&#xff0c;用服务名就能访问彼此。 就像家里连接到同一个 WiFi 的手机、电脑、电视&#xff0c;它们都能互相发现对方&#xff0c;Docker 里的容器也是一样 …...

嵌入式Linux 期末复习指南(上)

鉴于互联网上针对本科目相关复习视频及资料过少&#xff0c; 撰写本篇期末复习指南用作期末复习知识点扫盲&#xff0c;以应对本科期末考试及格之用。 由于任课老师并透露考试范围或任何有关试卷的相关信息&#xff0c;本篇指南基于教材、上机实验报告及作者经验编写&#xff0…...

SpringBoot3.2新特性:JdbcClient

文章目录 一、简介二、使用1、支持隐式位置参数2、通过索引设置位置参数3、支持 Name / Value 对命名参数4、通过 Map 设置命名参数5、使用 JdbClient 执行更新操作6、使用示例 参考资料 一、简介 Spring 6.1 中新添加了 JdbcClient 接口&#xff0c;它提供了 Fluent 风格的 A…...

Dify:启动 Web 服务的详细指南

1. 进入 web 目录 cd web解释&#xff1a; cd 是 “change directory” 的缩写&#xff0c;用于切换当前工作目录。您需要进入项目的 web 目录&#xff0c;这是前端代码所在的位置。在这个目录下&#xff0c;您可以执行构建和启动 Web 服务的相关命令。 2. 安装依赖 pnpm in…...

3.1 HarmonyOS NEXT分布式数据管理实战:跨设备同步、端云协同与安全保护

HarmonyOS NEXT分布式数据管理实战&#xff1a;跨设备同步、端云协同与安全保护 在万物互联的时代&#xff0c;数据的跨设备流转与安全共享是全场景应用的核心需求。HarmonyOS NEXT通过分布式数据管理技术&#xff0c;实现了设备间数据的实时同步与端云协同&#xff0c;为开发…...

Aop + 注解实现数据字典类型转换 EasyExcel导出

Aop 注解 实现数据字典类型转换 文章目录 Aop 注解 实现数据字典类型转换一、基础方式✅字典转换简介&#x1f449;实现步骤✅ 1. 定义自定义注解Dict ✅ 2. 定义查询字典项的两个方法✅ 3. 定义Aop拦截我们查询的方法✅ 4. VO映射类✅ 5. Controller层✅ 6. serviceImpl✅ 7. …...

Python 元组方法全集详解

Python 元组方法全集详解 在 Python 中,元组(tuple)是不可变序列类型,因此支持的操作比列表少。以下是元组支持的所有方法和操作: 一、元组核心方法 1. 创建元组 # 标准创建 t = (1, 2, 3) # (1, 2, 3) t = tuple(...

Selenium 中 JavaScript 点击操作的原理及应用

在 Selenium 中使用 JavaScript 执行点击操作&#xff08;如 driver.execute_script("arguments[0].click();", element)&#xff09;的原理涉及 WebDriver 架构、浏览器事件机制以及 JavaScript 对 DOM 的直接操作&#xff0c;以下是详细解释&#xff1a; 1. Selen…...

Xilinx超过256m bit flash固件跳转失败问题

问题描述 按照 链接: Xilinx 7系列fpga在线升级和跳转 这个方式跳转失败 问题排查 进一步排查现象如下 上面这个现象呈现出明显的以16m为周期的规律。感觉很大概率是因为flash超过了16m&#xff08;256bit&#xff09;导致的地址越界问题。另外我在CSDN上也找到类似的问题…...

SpringCloud 分布式锁Redisson锁的重入性与看门狗机制 高并发 可重入

可重入 Redisson 的锁支持 可重入性&#xff0c;这意味着同一个线程在获取锁后&#xff0c;如果再次尝试获取该锁&#xff0c;它可以成功地获得锁&#xff0c;而不会被阻塞。 每次一个线程成功获取锁后&#xff0c;它的持有次数会增加。当线程再次获取该锁时&#xff0c;Redi…...

02 APP 自动化-Appium 运行原理详解

环境搭建见 01 APP 自动化-环境搭建 文章目录 一、Appium及Appium自动化测试原理二、Appium 自动化配置项三、常见 ADB 命令四、第一个 app 自动化脚本 一、Appium及Appium自动化测试原理 Appium 跨平台、开源的 app 自动化测试框架&#xff0c;用来测试 app 应用程序&#x…...

由docker引入架构简单展开说说技术栈学习之路

想象一下&#xff0c;你开了一家线上小卖部&#xff08;单机版&#xff09;&#xff0c;突然爆单了怎么办&#xff1f;别急&#xff0c;技术架构的升级打怪之路&#xff0c;可比哆啦A梦的口袋还神奇&#xff01; 第1关&#xff1a;单枪匹马的创业初期&#xff08;单机架构&…...

linux 1.0.5

环境变量到底是什么 也就是windows上面的环境变量 就是这个东东&#xff0c;用户变量和系统变量&#xff0c;那这些到底是啥呢&#xff1f; 主包只是用过&#xff0c;配置来配置去的&#xff0c;就是不知道是啥意思 windows上面的环境变量 windows的ls命令是dir 输入calc可有…...

强化学习的前世今生(五)— SAC算法

书接前四篇 强化学习的前世今生&#xff08;一&#xff09; 强化学习的前世今生&#xff08;二&#xff09; 强化学习的前世今生&#xff08;三&#xff09;— PPO算法 强化学习的前世今生&#xff08;四&#xff09;— DDPG算法 本文为大家介绍SAC算法 7 SAC 7.1 最大熵强化…...

SQL进阶之旅 Day 8:窗口函数实用技巧

【SQL进阶之旅 Day 8】窗口函数实用技巧 在现代数据库开发中&#xff0c;处理复杂的业务逻辑和大规模数据时&#xff0c;仅仅依靠传统的GROUP BY和JOIN操作已经无法满足需求。**窗口函数&#xff08;Window Function&#xff09;**作为SQL标准的一部分&#xff0c;为开发者提供…...

生成对抗网络(GAN)基础原理深度解析:从直观理解到形式化表达

摘要 本文详细解析 生成对抗网络&#xff08;GAN&#xff09; 的 核心原理&#xff0c;从通俗类比入手&#xff0c;结合印假钞与警察博弈的案例阐述生成器 与 判别器 的对抗机制&#xff1b;通过模型结构示意图&#xff0c;解析 噪声采样、样本生成 及判别流程&#xff1b;基于…...

ubuntu 安装redis-6.2.9 源码安装和相关配置详解

目录 1 查看redis 软件列表 2 操作系统信息 3 redis软件下载并编译安装 4 redis 配置文件 5 启动redis 6 redis登录测试 7 设置redis开机启动 8 redis 配置详解 1 查看redis 软件列表 https://download.redis.io/releases/ 2 操作系统信息 rootu24-redis-120:~# cat /…...

c++之数组

目录 C数组基础概念 数组常见操作 二维数组定义与初始化 二维数组遍历方法 二维数组与函数 C数组基础概念 数组是C中用于存储相同类型元素的连续内存结构。通过索引访问元素&#xff0c;索引从0开始。数组大小必须在编译时确定&#xff0c;属于静态数据结构。 #include &…...

torch.distributed.launch 、 torchrun 和 torch.distributed.run 无法与 nohup 兼容

问题现象&#xff1a; 使用nohup 启动torch的分布式训练后&#xff0c; 由于ssh断开与服务器的连接&#xff0c; 导致训练过程出错&#xff1a; WARNING:torch.distributed.elastic.agent.server.api:Received 1 death signal, shutting down workers WARNING:torch.distribu…...

[SC]C++ 中 struct vs. class 的唯一区别

SystemC中 struct vs. class 的唯一区别 一、背景: 在 SystemC 示例里你会常看到这样的写法:SC_MODULE(Top) {// … ports, signals, 进程注册 … };而如果你展开宏 SC_MODULE(Top),它本质上就是:struct Top : sc_core::sc_module {// public:// Top(sc_core::sc_module_…...