Vue3核心源碼解析

/packages/complier-core

  • 定位??:??編譯時核心??,處理 Vue 模板的編譯邏輯。
  • ??核心功能??:
    • ??模板解析??:將?.vue?文件的模板語法(HTML-like)解析為 ??抽象語法樹 (AST)??。
    • ??轉換優化??:靜態節點提升(Hoist Static)、Patch Flags 標記(動態節點標記)。
    • ??代碼生成??:將 AST 轉換為可執行的 ??渲染函數(render?函數)??。
  • ??特點??:
    • 與平臺無關,不直接處理瀏覽器或 DOM,只負責語法層面的轉換。
    • 支持自定義編譯器指令(如?v-xxx?的自定義擴展)。

? vue3模板編譯原理

模板編譯分為三個階段:

1.解析階段

???????該階段的核心任務是將原始的 HTML 模板字符串轉換為初始的??抽象語法樹(AST)??。解析器通過??狀態機(State Machine)??逐字符掃描模板,識別出標簽、屬性、事件、插值表達式(如?{{ }})和組件標簽等語法單元。例如,對于?<div :class="cls">{{ text }}</div>,解析器會拆解出標簽名?div、動態屬性?:class?及其綁定表達式?cls,以及插值內容?text,最終構建出一棵樹形結構的原始 AST。此階段的 AST 僅保留模板的語法結構,尚未包含任何優化信息,但它為后續的轉換和代碼生成提供了基礎數據結構。

2.轉換階段(transform)

轉換階段是 Vue3 編譯流程的??核心優化環節??,通過對 AST 的多輪遍歷,實現語義分析和結構改造。這一階段包含多項關鍵技術:

1. Node Transforms 多步處理??
??作用??:通過一系列轉換函數(如?transformIftransformFor)逐層處理 AST 節點,將模板聲明式語法轉換為可執行的 JavaScript 邏輯。
??技術細節??:

  • 遞歸遍歷 AST,依次應用?v-if?→ 條件表達式、v-for?→ 循環結構等轉換規則
  • 動態綁定分析(如識別?:class?和?{{ text }}?的動態性差異)
  • 為后續優化階段(如靜態提升)提供結構化標記

2. ??靜態提升(Static Hoisting)??:識別純靜態內容(如無動態綁定的?<div>Static</div>),將其提取為常量并復用,避免重復創建虛擬節點。

3. ??Patch Flags 標記??:為動態節點添加二進制標志(如?CLASS | STYLE | PROPS),指導運行時僅對比變化的屬性,跳過全量 Diff。例如,動態綁定的?:class?和?{{ text }}?會被標記為不同的 Patch Flag。

4. ??塊追蹤(Block Tracking)??:將包含動態子節點的父節點標記為“塊”(Block),運行時通過?openBlock()(標記一個動態塊的開始,開始收集后續動態節點)?和?closeBlock()?(通過createBlock()自動關閉塊,無需顯式調用)控制更新范圍,縮小虛擬 DOM 的比對粒度。

5. ??緩存優化??:對事件處理函數和動態屬性值進行邏輯賦值緩存(如?_cache[0] || (_cache[0] = ...)),避免重復創建函數或計算表達式。

這些優化使得 AST 從“原始語法描述”升級為“富含運行時提示的中間形態”,為生成高效代碼奠定了基礎。

3.生成階段

生成階段將優化后的 AST 轉換為??可執行的渲染函數代碼??。代碼生成器遍歷 AST 節點,根據節點類型和優化標記拼接字符串,最終輸出類似?function render() { ... }?的 JavaScript 函數。例如,一個包含靜態提升和動態綁定的模板會被編譯為:

const _hoisted_1 = createVNode("div", null, "Static");  
function render() {  return (openBlock(), createBlock("div", null, [  _hoisted_1,  createVNode("p", null, ctx.text, 1 /* TEXT */)  ]));  
}  

此階段還會注入運行時代碼(如?createVNodeopenBlock),并確保生成的代碼符合 JavaScript 語法規范。最終輸出的渲染函數與 Vue 的運行時協作,在組件渲染時高效生成和更新虛擬 DOM。

/packages/reactivity

  • 定位??:??響應式系統的獨立實現??,Vue3 的「數據驅動」核心。
  • ??核心功能??:
    • ??依賴追蹤??:通過?Proxy?+?Reflect?實現數據的響應式代理。
    • ??核心 API??:
      • reactive:創建深度響應式對象。
      • ref:包裝基本類型值為響應式引用。
      • effect:副作用函數(替代 Vue2 的 Watcher)。
      • computed:計算屬性。
    • ??依賴收集與觸發??:通過?track?和?trigger?管理依賴關系。

proxy通過new Proxy(target,handler) 生成,new Proxy是JS原生API,用于創建一個代理對象,這個代理對象會包裝原始對象(target),并允許通過攔截器(handler)定義目標對象的操作行為

Proxy

一、new Proxy?的核心作用

1. 創建代理包裝器
  • ??輸入??:一個原始對象?target?和一個攔截器對象?handler
  • ??輸出??:生成一個??代理對象??(Proxy Instance),該代理對象會??轉發所有操作到原始對象??,但允許通過?handler?攔截特定操作
const raw = { a: 1 };
const handler = {get(target, key) {console.log(`讀取屬性 ${key}`);return target[key];}
};
const proxy = new Proxy(raw, handler);console.log(proxy.a); // 輸出 "讀取屬性 a",然后輸出 1
2. 定義攔截行為
  • handler?對象中可定義??陷阱函數(Traps)??,用于攔截 13 種對象操作(如?getsetdeleteProperty?等)
  • 當對 Proxy 實例進行操作時,會優先觸發對應的陷阱函數,未定義的陷阱會直接轉發到原始對象

二、生成的 Proxy 實例特點

1. ??透明訪問性??
  • ??鏡像原始對象??:Proxy 實例的屬性訪問、方法調用等行為會默認轉發到?target
    const raw = { x: 10 };
    const proxy = new Proxy(raw, {});
    console.log(proxy.x); // 10(未定義陷阱,直接訪問原始對象)
2. ??操作可攔截性??
  • ??精細攔截??:通過陷阱函數可攔截以下操作:
    陷阱函數攔截的操作
    get讀取屬性(如?obj.prop
    set設置屬性(如?obj.prop = 1
    hasin?操作符(如?'prop' in obj
    deletePropertydelete?操作符(如?delete obj.prop
    apply函數調用(如?fn()
    constructnew?操作符(如?new Fn()
    ownKeysObject.keys()for-in?循環等
3. ??引用獨立性??
  • ??獨立對象??:Proxy 實例是一個獨立的對象,與?target?是不同引用
    const raw = {};
    const proxy = new Proxy(raw, {});
    console.log(proxy === raw); // false
4. ??動態關聯性??
  • ??實時關聯??:Proxy 實例的操作會實時影響原始對象
    const raw = { a: 1 };
    const proxy = new Proxy(raw, {});
    proxy.a = 2;
    console.log(raw.a); // 2(修改代理實例會影響原始對象)
5. ??不可變性??
  • ??代理不可逆??:無法通過 Proxy 實例直接獲取原始的?handler?或?target(需通過特殊屬性或方法)
    const proxy = new Proxy({}, {});
    console.log(proxy); // 控制臺輸出 Proxy 對象,但無法直接看到 handler 和 target

三、在 Vue 3 中的特殊設計

在?packages/reactivity?模塊中,Vue 3 的?reactive()?函數生成的 Proxy 實例有以下特點:

1. ??響應式觸發器??
  • get?陷阱:觸發依賴收集(track
  • set?陷阱:觸發更新通知(trigger
2. ??嵌套對象懶代理??
  • 僅在訪問嵌套屬性時,才遞歸生成子 Proxy 對象
    const obj = reactive({ nested: { a: 1 } // 此時 nested 未被代理
    });
    console.log(obj.nested); // 訪問時生成嵌套 Proxy
3. ??原始對象標記??
  • 通過?ReactiveFlags.RAW?標記可獲取原始對象

四、與普通對象的對比

特性普通對象Proxy 實例
動態屬性攔截不支持支持(如新增屬性、刪除屬性)
引用關系獨立對象獨立對象,但操作關聯原始對象
操作攔截能力可攔截 13 種操作
性能開銷微小(但頻繁操作可能累積開銷)

五、示例:實現一個簡易響應式

const handler = {get(target, key) {console.log(`讀取 ${key}`);return target[key];},set(target, key, value) {console.log(`設置 ${key} 為 ${value}`);target[key] = value;return true;}
};const raw = { count: 0 };
const proxy = new Proxy(raw, handler);proxy.count++; // 輸出 "讀取 count",然后 "設置 count 為 1"

Reflect

一、Reflect?的本質

Reflect?是 ES6 引入的全局對象,提供了一套??與對象操作方法一一對應的函數式 API??。例如:

  • Reflect.get(target, key)?? 對應?target[key]
  • Reflect.set(target, key, value)?? 對應?target[key] = value
  • Reflect.has(target, key)?? 對應?key in target

其核心設計目標是??規范化對象操作??,使得原本隱式的操作(如屬性讀寫、in?操作符)可以通過函數顯式調用。


二、在 Proxy 陷阱中的必要性

當使用?Proxy?時,必須通過?Reflect?方法??轉發默認操作??,否則會導致原始對象行為的丟失。以下是關鍵原因:

1. ??保持?receiver?上下文正確性??

在訪問器屬性(getter/setter)中,this?的指向需要正確綁定到代理對象(而非原始對象)。
通過?Reflect.get(target, key, receiver)?的第三個參數?receiver,可以確保?this?指向代理對象。

??示例:??

const raw = {_value: 0,get value() {return this._value; // this 必須指向代理對象}
};const proxy = new Proxy(raw, {get(target, key, receiver) {// 使用 Reflect 傳遞 receiverreturn Reflect.get(target, key, receiver);}
});console.log(proxy.value); // 正確觸發代理的 get 陷阱
2. ??返回值標準化??

Reflect?方法返回布爾值或操作結果,與 Proxy 陷阱的返回值要求一致。例如:

  • Reflect.set?返回?boolean?表示是否設置成功
  • Reflect.deleteProperty?返回?boolean?表示是否刪除成功

??示例:??

const proxy = new Proxy({}, {set(target, key, value, receiver) {// 必須返回布爾值return Reflect.set(target, key, value, receiver);}
});
3. ??避免破壞對象內部方法??

直接操作?target[key]?可能繞過對象內部的?[[Get]][[Set]]?等內部方法,而?Reflect?確保操作符合規范。

在 JavaScript 中,直接通過?target[key]?操作對象屬性可能會繞過對象內部的?[[Get]]?和?[[Set]]?等內部方法,原因如下:


一、[[Get]]?和?[[Set]]?的本質

對象的屬性訪問(如?obj.prop)和賦值(如?obj.prop = value)本質上會觸發對象內部的?[[Get]]?和?[[Set]]?方法。這些內部方法負責:

  1. ??訪問器屬性(getter/setter)的執行??
  2. ??原型鏈的查找??
  3. ??屬性描述符(如?writableconfigurable)的校驗??

二、直接操作?target[key]?的問題

當在 Proxy 的陷阱函數中直接操作?target[key]?時,可能繞過以下關鍵邏輯:

1. ??繞過訪問器屬性(getter/setter)??

如果目標對象(target)的屬性是訪問器屬性(定義了?get?或?set),直接通過?target[key]?訪問或賦值會??跳過訪問器邏輯??,直接操作底層值。

??示例:??

const obj = {get value() {console.log("getter 被調用");return this._value;},set value(v) {console.log("setter 被調用");this._value = v;}
};const proxy = new Proxy(obj, {get(target, key) {// 直接返回 target[key],繞過 getterreturn target[key]; // ? 錯誤方式},set(target, key, value) {// 直接賦值 target[key],繞過 settertarget[key] = value; // ? 錯誤方式return true;}
});proxy.value = 1; // 不會觸發 setter 的 console.log
console.log(proxy.value); // 不會觸發 getter 的 console.log
  • ??結果??:直接操作?target[key]?會導致訪問器邏輯被繞過,_value?被直接讀寫。
2. ??破壞?this?綁定??

訪問器屬性中的?this?默認指向原始對象(target),而非代理對象(proxy)。這會導致依賴代理對象的邏輯(如嵌套響應式)失效。

??示例:??

const raw = {get value() {return this._value; // this 指向 raw,而非 proxy}
};const proxy = new Proxy(raw, {get(target, key) {return target[key]; // ? this 錯誤綁定到 raw}
});proxy._value = 42;
console.log(proxy.value); // 42,但若 proxy 有攔截邏輯,this 指向錯誤會導致問題
3. ??繞過嵌套 Proxy??

如果目標對象本身是另一個 Proxy,直接操作?target[key]?會??繞過其陷阱函數??,直接訪問原始值。

??示例:

const inner = new Proxy({ a: 1 }, {get(target, key) {console.log("inner 的 get 陷阱");return Reflect.get(target, key);}
});const outer = new Proxy(inner, {get(target, key) {// 直接訪問 target[key],繞過 inner 的 Proxy 陷阱return target[key]; // ? 不會觸發 inner 的 get 陷阱}
});console.log(outer.a); // 直接輸出 1,無日志
4. ??忽略原型鏈和屬性描述符??

直接操作?target[key]?可能繞過原型鏈查找和屬性描述符(如?writable)的校驗。

??示例:??

const parent = { a: 1 };
const child = Object.create(parent);
const proxy = new Proxy(child, {get(target, key) {return target[key]; // ? 直接返回 undefined(不會查找原型鏈)}
});console.log(proxy.a); // undefined(正確應為 1)

三、為什么?Reflect?能避免這些問題?

Reflect?方法(如?Reflect.get)會嚴格遵循對象的?[[Get]]?和?[[Set]]?內部方法,確保以下行為:

1. ??觸發訪問器屬性??
const proxy = new Proxy(obj, {get(target, key, receiver) {return Reflect.get(target, key, receiver); // ? 觸發 getter},set(target, key, value, receiver) {return Reflect.set(target, key, value, receiver); // ? 觸發 setter}
});
2. ??綁定正確的?this(通過?receiver?參數)??
Reflect.get(target, key, receiver);
  • receiver?參數確保訪問器屬性中的?this?指向代理對象(而非原始對象)。
3. ??處理原型鏈和屬性描述符??
Reflect.get(target, key, receiver); // ? 沿原型鏈查找屬性
Reflect.set(target, key, value, receiver); // ? 校驗 `writable` 等屬性
4. ??支持嵌套 Proxy??
// 通過 Reflect 觸發內層 Proxy 的陷阱
Reflect.get(innerProxy, key, receiver); // ? 觸發 innerProxy 的 get 陷阱

四、關鍵對比

操作方式直接操作?target[key]使用?Reflect
??訪問器屬性??繞過 getter/setter正確觸發 getter/setter
??this?綁定??指向原始對象(target指向代理對象(通過?receiver
??原型鏈??可能中斷查找完整執行原型鏈查找
??嵌套 Proxy??繞過內層 Proxy 的陷阱觸發內層 Proxy 的陷阱
??屬性描述符校驗??忽略?writableconfigurable?等嚴格校驗

三、在 Vue 響應式系統中的具體應用

Vue 3 的?reactive()?函數通過?Proxy?+?Reflect?實現響應式代理。以下是核心場景:

1. ??依賴收集(Track)??

在?get?陷阱中,通過?Reflect.get?獲取值,并收集依賴:

function createGetter() {return function get(target: object, key: string | symbol, receiver: object) {// 使用 Reflect.get 獲取原始值const res = Reflect.get(target, key, receiver);// 依賴追蹤track(target, TrackOpTypes.GET, key);// 遞歸代理嵌套對象if (isObject(res)) {return reactive(res);}return res;};
}
2. ??觸發更新(Trigger)??

在?set?陷阱中,通過?Reflect.set?設置值,并觸發更新:

function createSetter() {return function set(target: object,key: string | symbol,value: unknown,receiver: object): boolean {// 獲取舊值const oldValue = (target as any)[key];// 使用 Reflect.set 設置值const result = Reflect.set(target, key, value, receiver);// 觸發更新(僅當值變化時)if (hasChanged(value, oldValue)) {trigger(target, TriggerOpTypes.SET, key);}return result;};
}
3. ??處理?has?和?ownKeys?陷阱??

攔截?in?操作符和?Object.keys()


四、Reflect?與直接操作對象的區別

操作方式直接操作對象(如?target[key]使用?Reflect
??this 綁定??this?指向原始對象通過?receiver?參數控制?this?指向
??返回值??無標準返回值(可能拋出錯誤)標準化布爾值或操作結果
??原型鏈處理??可能無法正確處理繼承屬性嚴格遵循對象原型鏈規則
??函數式調用??無法以函數形式調用函數式 API,便于組合和抽象

五、關鍵設計思想總結

  1. ??行為一致性??
    Reflect?方法嚴格遵循 ECMAScript 規范,確保代理對象的行為與原對象一致。

  2. ??代理鏈完整性??
    在多層代理(如 Vue 的?readonly(reactive(obj)))中,Reflect?能正確傳遞?receiver,維護代理鏈的上下文。

  3. ??錯誤處理簡化??
    通過?Reflect?的布爾返回值,避免手動處理異常(如設置不可寫屬性時的?TypeError)。


示例:沒有?Reflect?的陷阱

若在 Proxy 陷阱中不使用?Reflect,會導致意外行為:

const raw = { a: 1 };
const proxy = new Proxy(raw, {get(target, key) {// 錯誤!未使用 Reflect.get,this 指向錯誤return target[key];},set(target, key, value) {// 錯誤!未返回布爾值target[key] = value;return true;}
});const child = { __proto__: proxy };
console.log(child.a); // 期望觸發 get 陷阱,但實際不會!

/packages/runtime-core

  • 定位??:??運行時核心??,實現 Vue 組件的生命周期、虛擬 DOM、渲染調度等。
  • ??核心功能??:
    • ??虛擬 DOM 算法??:Diff 算法(patchKeyedChildren)、節點 Patch 邏輯。
    • ??組件系統??:組件實例化、Props/Emits 處理、Slots 管理。
    • ??生命周期鉤子??:onMountedonUpdated?等 Composition API 的實現。
    • ??自定義渲染器??:提供?createRenderer?API,支持跨平臺渲染(如小程序、Canvas)。
  • ??特點??:
    • 平臺無關,不直接操作 DOM,依賴外部傳入的 ??宿主環境 API??。
    • 包含 Vue 的核心邏輯,但需與?runtime-dom?結合才能用于瀏覽器。

/packages/runtime-dom

  • 定位??:??瀏覽器端運行時??,提供 DOM 相關的原生操作。
  • ??核心功能??:
    • ??DOM 操作 API??:封裝?document.createElementparent.appendChild?等原生方法。
    • ??事件處理??:標準化事件監聽(如?onClick?的自動轉換)。
    • ??屬性處理??:處理 HTML Attributes、DOM Properties、類名、樣式等。
  • ??特點??:
    • 基于?runtime-core?實現,是 Vue 在瀏覽器環境下的 ??默認渲染器??。
    • 導出?createApp?等瀏覽器端專用 API。

/packages/runtime-test

  • ??定位??:??測試用運行時??,用于單元測試場景。
  • ??核心功能??:
    • ??輕量級 DOM 模擬??:提供內存中的虛擬 DOM 操作,避免依賴真實瀏覽器環境。
    • ??序列化輸出??:將渲染結果序列化為字符串,方便斷言(Assertion)。
    • ??生命周期追蹤??:記錄組件生命周期鉤子的調用順序。
  • ???使用場景??:
    • 測試組件渲染邏輯,不依賴?jsdom?或瀏覽器。
    • 驗證虛擬 DOM 的 Diff 算法是否正確。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/79962.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/79962.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/79962.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

n8n 中文系列教程_05.如何在本機部署/安裝 n8n(詳細圖文教程)

n8n 是一款強大的開源工作流自動化工具&#xff0c;可幫助你連接各類應用與服務&#xff0c;實現自動化任務。如果你想快速體驗 n8n 的功能&#xff0c;本機部署是最簡單的方式。本教程將手把手指導你在 Windows 或 MacOS 上通過 Docker 輕松安裝和運行 n8n&#xff0c;無需服務…

【python】pyCharm常用快捷鍵使用-(2)

pyCharm常用快捷鍵使用 快速導入任意類 【CTRLALTSPACE】代碼補全【CTRLSHIFTENTER】代碼快速修正【ALTENTER】代碼調試快捷鍵

Docker 鏡像、容器和 Docker Compose的區別

前言&#xff1a;Docker 的鏡像、容器和 Docker Compose 是容器化技術的核心組件&#xff0c;以下是對它們的詳細解析及使用場景說明。 ??1、Docker 鏡像&#xff08;Image&#xff09;?? ??定義??&#xff1a; 鏡像是只讀模板&#xff0c;包含運行應用程序所需的代碼、…

算法——背包問題(分類)

背包問題&#xff08;Knapsack Problem&#xff09;是一類經典的組合優化問題&#xff0c;廣泛應用于資源分配、投資決策、貨物裝載等領域。根據約束條件和問題設定的不同&#xff0c;背包問題主要分為以下幾種類型&#xff1a; 1. 0-1 背包問題&#xff08;0-1 Knapsack Probl…

多路由器通過RIP動態路由實現通訊(單臂路由)

多路由器通過RIP動態路由實現通訊&#xff08;單臂路由&#xff09; R1(開啟端口并配置IP) Router>en Router#conf t Router(config)#int g0/0 Router(config-if)#no shu Router(config-if)#no shutdown Router(config-if)#ip add 192.168.10.254 255.255.255.0 Router(c…

從底層設計原理分析并理解SQL 的執行順序

?一、執行順序的底層設計原理?? ??1. 數據源的確定與連接&#xff08;FROM → ON → JOIN&#xff09;?? ??FROM??&#xff1a;數據庫首先需要確定數據的物理來源&#xff0c;從磁盤加載表或子查詢的原始數據。此時尚未應用任何篩選&#xff0c;僅讀取元數據&#…

游戲引擎學習第237天:使用 OpenGL 顯示圖像

win32_game.cpp: 禁用 PFD_DOUBLEBUFFER 我們正在處理一個新的開發階段&#xff0c;目標是在使用 OpenGL 渲染的同時能正常通過 OBS 進行直播。昨天我們已經嘗試了一整天來解決這個問題&#xff0c;希望能找到一種方式讓 OBS 能正確地捕捉到 OpenGL 的窗口畫面。雖然我們不確定…

(二)mac中Grafana監控Linux上的MySQL(Mysqld_exporter)

框架&#xff1a;GrafanaPrometheusMysqld_exporter 一、監控查看端安裝 Grafana安裝-CSDN博客 普羅米修斯Prometheus監控安裝&#xff08;mac&#xff09;-CSDN博客 1.啟動Grafana服務 brew services start grafana 打開瀏覽器輸入http://localhost:3000進入grafana登錄…

GitHub 趨勢日報 (2025年04月17日)

本日報由 TrendForge 系統生成 https://trendforge.devlive.org/ &#x1f4c8; 今日整體趨勢 Top 10 排名項目名稱項目描述今日獲星總星數語言1Anduin2017/HowToCook程序員在家做飯方法指南。Programmer’s guide about how to cook at home (Simplified Chinese onl…? 224…

(一)mac中Grafana監控Linux上的CPU等(Node_exporter 安裝使用)

框架&#xff1a;GrafanaPrometheusNode_exporter 機器狀態監控(監控服務器CPU,硬盤&#xff0c;網絡等狀態) Node_exporter安裝在被測服務器上&#xff0c;啟動服務 各步驟的IP地址要換為被測服務器的IP地址Prometheus.yml的 targets值網頁訪問的ip部分grafana添加數據源的…

java IO/NIO/AIO

(?▽?)曼波~~~~&#xff01;讓曼波用最可愛的賽馬娘方式給你講解吧&#xff01;(? ???ω??? ?) &#x1f3a0;曼波思維導圖大沖刺&#xff08;先看框架再看細節哦&#xff09;&#xff1a; &#x1f4da; 解釋 Java 中 IO、NIO、AIO 的區別和適用場景&#xff1a; …

Silverlight發展歷程(微軟2021年已經停止支持Silverlight 5)

文章目錄 Microsoft Silverlight 發展歷程引言起源與背景&#xff08;2006-2007&#xff09;互聯網技術格局與微軟的挑戰WPF/E 項目的啟動 Silverlight 1.0 的誕生&#xff08;2007&#xff09;正式命名與首次發布初步的市場定位 Silverlight 2.0&#xff1a;真正的突破&#x…

【大數據、數據開發與數據分析面試題匯總(含答案)】

在大數據、數據開發與數據分析領域的面試中&#xff0c;扎實掌握各類知識點至關重要。以下是精心整理的面試題&#xff0c;涵蓋單選題和多選題&#xff0c;助你備考一臂之力。 試題目錄 大數據、數據開發與數據分析高頻面試題解析1. 數據倉庫分層架構設計2. 維度建模與范式建模…

Docker部署禪道21.6開源版本

將數據庫相關環境變量分開&#xff0c;增加注釋或空格使得命令更易讀。 如果你的 MySQL 主機、端口等配置沒有變化&#xff0c;應該確保這些信息是安全的&#xff0c;并考慮使用 Docker secrets 或環境變量配置來避免直接暴露敏感信息。 docker run -d -it --privilegedtrue …

Yocto項目實戰教程 · 第4章:4.2小節-菜譜

&#x1f50d; B站相應的視頻教程&#xff1a; &#x1f4cc; Yocto項目實戰教程-第4章-4.2小節-菜譜 記得三連&#xff0c;標為原始粉絲。 在 Yocto 項目中&#xff0c;**菜譜&#xff08;Recipe&#xff09;**承載了包的配置信息、源碼獲取方式、編譯與安裝步驟&#xff0c;是…

【pytorch】torch.nn.Unfold操作

說明 一個代碼里涉及到了unfold的操作&#xff0c;看了半天官網都沒整明白維度怎么變化的&#xff0c;參考這個鏈接搞明白了&#xff1a; https://blog.csdn.net/ViatorSun/article/details/119940759 https://zhuanlan.zhihu.com/p/361140988 維度計算 輸入&#xff08; N,…

Linux 固定IP地址

一.查看網口狀態&#xff1a; $ ip a 二.配置靜態IP文件&#xff1a; $ sudo vi /etc/network/interface auto eth0 iface eth0 inet static address 192.168.0.252 gateway 192.168.0.1 netmask 255.255.255.0 #network 192.168.0.0 #broadcast 192.168.0.255 三.重啟網卡讓新…

android的 framework 有哪些知識點和應用場景

Android Framework 知識點 1. 四大組件 Activity&#xff08;活動&#xff09; 是 Android 應用中最基本的組件&#xff0c;用于實現用戶界面。一個 Activity 通常對應一個屏幕的內容。有自己的生命周期&#xff0c;包括 onCreate、onStart、onResume、onPause、onStop、onDe…

如何在PDF.js中改造viewer.html以實現PDF的動態加載

在PDF.js中改造viewer.html實現PDF動態加載&#xff0c;需結合參數傳遞、文件流處理及跨域配置等技術。以下是綜合多個技術方案的核心實現步驟&#xff1a; ?一、基礎參數傳遞法? 1. ?URL參數動態加載? 通過修改viewer.html的URL參數傳遞PDF路徑&#xff0c;適用于靜態文…

組件之間的數據通信方式

Vue 的傳值方式&#xff08;即組件之間的數據通信方式&#xff09;根據組件關系不同&#xff08;父子、兄弟、跨層級&#xff09;有所區別。下面是常見的傳值方式&#xff0c;按使用場景來分類&#xff1a; 一、父子組件傳值 1. props&#xff08;父 -> 子&#xff09; 父…