前端開發崗模擬面試題套卷A答案及解析(一)技術面部分

前端開發崗模擬面試題套卷A答案及解析(一)技術面部分

(一)技術面

一、JavaScript核心技術(ES6+)

1-1、實現防抖函數
function debounce(fn, delay) {let timer = null;return function(...args) {clearTimeout(timer); // 清除已有定時器timer = setTimeout(() => { fn.apply(this, args); // 綁定正確this}, delay);};
}
// 應用場景:搜索框輸入聯想、窗口resize事件
1-2、其應用場景解釋

防抖函數(debounce)核心作用是 限制高頻觸發的函數執行頻率,確保連續多次觸發時,只在最后一次觸發后延遲執行一次目標函數。

postscript:
代碼逐行解釋

1、let timer = null
利用閉包特性保存定時器標識,保證多次調用時共享同一個 timer。
2、clearTimeout(timer)
每次觸發時,先清除上一次的定時器,重置倒計時。
3、setTimeout(() => { fn.apply(this, args) }, delay)
延遲 delay 毫秒后執行目標函數 fn,并通過 apply 確保 this 指向和參數傳遞正確性。

核心特性

特性說明
延遲執行觸發后等待 delay 時間再執行
重置機制新觸發會覆蓋舊定時器
上下文綁定通過apply保留原函數 this
1-3 應用場景舉例

1、搜索框輸入聯想

  • 問題:用戶連續輸入時,每次按鍵都會觸發搜索請求,導致請求爆炸。
  • 解決:防抖控制在用戶停止輸入 300ms 后發送請求。
    示例代碼:
const searchInput = document.getElementById('search');
searchInput.addEventListener('input', debounce(function() {// 發送搜索請求
}, 300));

2、窗口resize事件

  • 問題:調整窗口大小時頻繁觸發重繪邏輯,引發性能問題。
  • 解決:防抖確保只在調整結束后計算布局。
window.addEventListener('resize', debounce(function() {// 更新布局
}, 200));

3、按鈕防重復提交

  • 問題:用戶快速點擊按鈕導致重復提交請求。
  • 解決:防抖屏蔽短時間內的多次點擊。
submitBtn.addEventListener('click', debounce(function() {// 提交表單
}, 1000));

與節流(throttle)的區別

區別項&技術名防抖(debounce)節流(throttle)
邏輯只執行最后一次觸發固定時間間隔執行一次
場景輸入聯想、resize滾動事件、鼠標移動

postscript:
回答得分點

1、正確識別防抖函數(占 40%)
? 明確說出函數用途是“限制高頻觸發函數的執行頻率”。
2、閉包與定時器機制(占 30%)
? 解釋 timer 閉包保存狀態和 clearTimeout 的重置邏輯。
3、應用場景舉例(占 20%)
? 至少給出兩個合理場景(如搜索框、resize)。
4、附加細節(占 10%)
? 提及 apply 的上下文綁定作用。
? 對比節流函數(throttle)的差異。

如果候選人能結合代碼實現細節和實際業務場景作答,即可判定為滿分回答。

2-1、閉包(Closure)原理

閉包是 函數與其詞法作用域(lexical scope)的組合,使得內部函數可以訪問外部函數的變量,即使外部函數已執行完畢。其本質是 函數在定義時捕獲并保留了其所在作用域的引用
實現機制
1、詞法環境(Lexical Environment)
函數在定義時記錄其所在作用域的變量引用,形成閉包鏈。
2、垃圾回收豁免
被閉包引用的變量不會被回收,即使外部函數已銷毀。
3、私有性
通過閉包可以實現變量隱藏(類似私有變量)。
自增ID生成器實現
代碼實現

function createIdGenerator(initialId = 0) {let id = initialId; // 通過閉包保留id狀態return function() {return ++id; // 每次調用自增};
}// 使用示例
const generator = createIdGenerator();
console.log(generator()); // 1
console.log(generator()); // 2 

關鍵特性

特性說明
狀態持久化通過閉包保存id變量狀態
隔離性每次調用工廠函數生成獨立計數器
可定制初始值支持傳入initialId參數

postscript:
閉包原理得分點
1、作用域鏈描述
(30%)
? 解釋函數定義時捕獲外部作用域變量的機制

2、生命周期控制(30%)
? 說明閉包如何阻止變量被垃圾回收

3、實際應用場景(20%)
? 結合ID生成器案例說明狀態保持

4、延伸擴展(20%)
? 提及閉包在模塊化/私有變量中的應用
ID生成器得分點

評分項滿分扣分點示例
閉包正確使用4未使用閉包(直接返回全局變量)
自增邏輯正確3后置遞增(id++)導致從0開始
支持多實例獨立2多個生成器共享同一計數器
參數可配置性1未實現initialid參數

進階追問示例
1、如何實現ID重置功能?

function createIdGenerator() {let id = 0;return {next: () => ++id,reset: () => id = 0};
}

2、多個生成器之間如何避免沖突?
每個生成器通過獨立閉包隔離狀態,天然線程安全。
通過閉包實現的狀態管理是前端高頻考點,建議結合內存管理(如閉包泄露場景)深化理解。

3-1、手寫Promise.all實現,并處理錯誤情況的代碼及詳細解釋:
function myPromiseAll(promises) {return new Promise((resolve, reject) => {// 檢查輸入是否為可迭代對象if (typeof promises?.[Symbol.iterator] !== 'function') {reject(new TypeError('Argument is not iterable'));return;}const promiseArray = Array.from(promises);const results = new Array(promiseArray.length);let completedCount = 0;let hasRejected = false;// 處理空數組的情況if (promiseArray.length === 0) {resolve(results);return;}for (let i = 0; i < promiseArray.length; i++) {// 將每個元素轉為 PromisePromise.resolve(promiseArray[i]).then((result) => {if (hasRejected) return; // 已失敗則忽略results[i] = result; // 按索引存儲結果completedCount++;// 全部完成時 resolveif (completedCount === promiseArray.length) {resolve(results);}}).catch((error) => {if (!hasRejected) {hasRejected = true;reject(error); // 首個錯誤直接 reject}});}});
}

核心實現要點
1、類型檢查

  • 使用Symbol.iterator 驗證輸入是否為可迭代對象(如數組)。
  • 非可迭代對象直接reject類型錯誤。
    2、邊界處理
  • 空數組直接resolve([])。
  • 非Promise值通過 Promise.resolve()包裝。
    3、狀態管理
  • results 數組按索引存儲結果,保證輸出順序。
  • completedCount 計數器跟蹤完成數量。
  • hasRejected標志位確保只reject一次。
    4、錯誤處理
  • 任何一個Promise失敗立即終止,后續結果被忽略。
  • 通過hasRejected防止多次調用reject

使用示例

// 成功場景
myPromiseAll([Promise.resolve(1),Promise.resolve(2)
]).then(console.log); // 輸出: [1, 2]// 失敗場景
myPromiseAll([Promise.resolve(1),Promise.reject('error')
]).catch(console.log); // 輸出: 'error'// 非 Promise 值
myPromiseAll([1, 2, 3]).then(console.log); // 輸出: [1, 2, 3]// 空數組
myPromiseAll([]).then(console.log); // 輸出: []

與原生的差異對比

特性原生Promise.all手寫實現
錯誤處理立即終止完全一致
非Promise值自動包裝為Promise通過Promise.resolve實現
結果順序嚴格按輸入順序完全一致
可迭代對象支持支持通過類型檢查實現

得分點解析

得分項分值扣分點示例
正確返回Promise實例2未返回Promise對象
處理可迭代對象2未校驗輸入類型導致奔潰
結果順序保留3使用push()導致順序錯亂
錯誤立即終止3未處理多個reject調用
非Promise值兼容2未使用Promise.resolve包裝
空數組處理1未特殊處理空數組場景

通過以上實現,完整復現了 Promise.all 的核心功能,并嚴格處理了邊界條件和異常場景。

4 Proxy實現對象屬性訪問監控

基礎實現

function createObservedObject(target) {const handler = {get(target, property, receiver) {console.log(`[監控] 讀取屬性 ${property}`);// 遞歸代理嵌套對象const value = Reflect.get(target, property, receiver);return typeof value === 'object' && value !== null ? createObservedObject(value) // 深度代理: value;},set(target, property, value, receiver) {console.log(`[監控] 設置屬性 ${property} = ${value}`);return Reflect.set(target, property, value, receiver);}};return new Proxy(target, handler);
}// 使用示例
const user = createObservedObject({name: 'Alice',address: {city: 'Beijing'},scores: [90, 85]
});console.log(user.name); // 輸出監控日志
console.log(user.address.city); // 觸發嵌套對象監控
user.scores.push(95); // 監控數組操作

核心機制
1、屬性讀取監控

  • get陷阱:攔截所有屬性訪問,包括嵌套對象
  • 遞歸代理:對對象/數組類型屬性值進行深度代理
  • Reflect轉發:保持原對象的默認行為
    2、屬性修改監控
  • set陷阱:攔截所有屬性賦值操作
  • 數組方法攔截push/pop等操作會觸發get + set
    進階優化版本
function createDeepProxy(target, cache = new WeakMap()) {// 防止重復代理和循環引用if (cache.has(target)) return cache.get(target);const handler = {get(target, prop) {console.log(`Read ${prop}`);const value = Reflect.get(...arguments);// 自動代理對象/數組/Set/Map等引用類型if (typeof value === 'object' && value !== null) {return createDeepProxy(value, cache);}return value;},set(target, prop, value) {console.log(`Set ${prop} to`, value);return Reflect.set(...arguments);}};const proxy = new Proxy(target, handler);cache.set(target, proxy); // 緩存已代理對象return proxy;
}

關鍵特性對比

特性基礎版本優化版本
循環引用處理? 會棧溢出? WeakMap 緩存解決
復合數據類型支持對象/數組對象/數組/Set/Map
性能優化? 重復創建代理? 緩存機制
監控范圍直接屬性訪問包括原型鏈方法調用

應用場景
1、數據變更追蹤

  • Vue3響應式系統的核心實現原理
  • 實現自動化的表單數據校驗

2、調試工具

  • 實時監控對象狀態變化
  • 記錄屬性訪問歷史

3、權限控制

  • 禁止訪問私有屬性(屬性名前帶)
get(target, prop) {if (prop.startsWith('_')) {throw new Error('私有屬性禁止訪問');}return Reflect.get(...arguments);
}

4、性能分析

  • 統計熱點屬性訪問頻率
  • 檢測內存泄漏(長時間未被訪問的屬性)

注意事項
1、Proxy局限性

  • 無法監控Object.keys()等靜態方法
  • JSON.stringfy()無效

2、性能影響

  • 深度代理大型對象時會有內存開銷
  • 生產環境建議選擇性代理關鍵數據

3、瀏覽器兼容性

  • IE不支持Proxy, 需要用polyfill如 proxy-polyfill

面試得分點
1、基礎實現
(40%)

  • 正確使用Proxy的 get/set 陷阱
  • 處理基本數據類型和引用類型差異

2、深度代理(30%)

  • 遞歸代理嵌套對象
  • 處理數組等特殊對象

3、異常處理(20%)

  • 循環引用解決方案
  • 私有屬性訪問控制

4、擴展認知(10%)

  • 能夠關聯到Vue3響應式原理
  • 提出實際應用場景

通過Proxy實現的屬性監控是前端高級開發的必備技能,建議結合具體框架源碼(如Vue3 的 reactive模塊)深入理解。

5、Event Loop核心機制

JavaScript 是單線程語言,通過 **事件循環(Event Loop)**處理異步操作。其運行機制分為以下層級:

層級內容優先級
調用棧同步代碼執行(后進先出)最高
微任務Promise.then、MutationObserver
宏任務setTimeout、setInterval、I / O

執行規則:
1、同步代碼立即執行,清空調用棧
2、執行所有微任務(直到微任務隊列為空)
3、執行一個宏任務
4、重復步驟2-3
題目代碼分析

console.log(1);
setTimeout(() => console.log(2), 0);
Promise.resolve().then(() => console.log(3));
console.log(4);

執行步驟分解
1、同步階段

  • console.log(1)—> 輸出1
  • setTimeout 回調注冊到宏任務隊列
  • Promise.then回調注冊到微任務隊列
  • console.log(4)—>輸出4
    此時輸出:1 —> 4

2、微任務階段:

  • 檢查微任務隊列,執行()=>console.log(3)——> 輸出3
    此時輸出:1 —> 4 —> 3

3、宏任務階段:

  • 取出第一個宏任務(SetTimeout回調),執行()=>console.log(2)—>輸出2

最終輸出:1—> 4 —> 3 —> 2
關鍵原理圖示

[調用棧]1. 執行 console.log(1)
2. 將 setTimeout 回調加入宏任務隊列
3. 將 Promise.then 回調加入微任務隊列
4. 執行 console.log(4)[微任務隊列]
↓ 執行所有微任務 → console.log(3)[宏任務隊列]
↓ 執行一個宏任務 → console.log(2)

常見誤區
1、零延遲不代表立即執行
setTimeout(fn, 0)的實質是最快 4ms (瀏覽器規范限制)后加入宏任務隊列,而非立即執行。
2、微任務優先級碾壓宏任務
即使宏任務進入隊列,也必須等待當前所有微任務執行完畢。
3、嵌套任務的影響
若在微任務中創建新的微任務,會持續執行直到隊列清空:

Promise.resolve().then(() => {console.log(3);Promise.resolve().then(() => console.log(5)); // 新增微任務
});

輸出順序為:1 —>4 —> 3 —> 5—>2
面試得分點

考察維度滿分回答要點
階段劃分明確同步/微任務/宏任務執行順序
隊列機制解釋微任務隊列清空后才執行宏任務
API分類正確區分宏任務與微任務API
瀏覽器差異提及Node.js與瀏覽器的差異

掌握 Event Loop機制是前端核心能力,建議通過 Loupe 可視化工具加深理解。

二、Vue架構深度

1、Vue3響應式原理(對比Vue2)

Vue2使用Object.defineProperty遞歸遍歷對象屬性實現響應式,存在無法檢測新增屬性和數組下標變化的問題。Vue3改用Proxy代理對象,可監聽動態屬性增減和更多操作類型(如delete)。同時引入Reflect操作對象,配合effect-tracker實現更精準的依賴收集。組件實例層面通過Composition API實現邏輯復用,相比Vue2的Options API更靈活

postScript:
得分點:

  • 準確對比兩代實現差異(3分)
  • 指出Proxy優勢(2分)
  • 說明Composition API作用(2分)
  • 提及Refleck使用(1分)
2、Vue自定義拖拽指令

核心邏輯
1、事件驅動:通過 mousedown 觸發拖拽, mousemove 更新位置,mouseup 結束拖拽
2、坐標計算:基于 clientx / clientv 計算鼠標相對元素的偏移量
3、邊界處理:可選限制元素在可視區域內移動((如搜索結果[7]的彈窗拖拽實現))

// 注冊全局指令(可放入單獨文件)
Vue.directive('drag',  {inserted(el, binding) {// 設置元素定位方式(需確保元素可定位)el.style.position  = 'absolute';// 獲取拖拽觸發區域(默認整個元素可拖拽)const dragHandle = binding.value?.handle  ? el.querySelector(binding.value.handle)  : el;dragHandle.style.cursor  = 'move';let startX = 0, startY = 0, initialLeft = 0, initialTop = 0;// 鼠標按下事件 const onMouseDown = (e) => {e.preventDefault(); // 記錄初始位置 startX = e.clientX; startY = e.clientY; initialLeft = el.offsetLeft; initialTop = el.offsetTop; document.addEventListener('mousemove',  onMouseMove);document.addEventListener('mouseup',  onMouseUp);};// 鼠標移動事件 const onMouseMove = (e) => {const dx = e.clientX  - startX;const dy = e.clientY  - startY;// 計算新位置 let newLeft = initialLeft + dx;let newTop = initialTop + dy;// 邊界限制(可選)if (binding.value?.boundary)  {newLeft = Math.max(0,  Math.min(newLeft,  window.innerWidth  - el.offsetWidth)); newTop = Math.max(0,  Math.min(newTop,  window.innerHeight  - el.offsetHeight)); }// 更新元素位置 el.style.left  = `${newLeft}px`;el.style.top  = `${newTop}px`;};// 鼠標松開事件 const onMouseUp = () => {document.removeEventListener('mousemove',  onMouseMove);document.removeEventListener('mouseup',  onMouseUp);};// 綁定事件 dragHandle.addEventListener('mousedown',  onMouseDown);// 保存引用用于解綁 el.__vueDragHandler__ = onMouseDown;},unbind(el) {// 移除事件監聽 const dragHandle = el.__vueDragHandler__?.currentTarget || el;dragHandle.removeEventListener('mousedown',  el.__vueDragHandler__);}
});

示例代碼解說

關鍵優化點
  • 定位方式自動檢測:強制設置position: absolute避免用戶未設置 [參考2] 、 [參考3]
  • 事件解綁機制:在unbind階段移除監聽防止內存泄漏
  • 性能優化:使用requestAnimationFrame優化高頻觸發(示例未展示,可自行擴展)
  • 觸摸屏支持:添加touchstart/touchmove事件實現移動端適配
實現效果對比
功能特性本方案實現參考方案[7]實現
基礎拖拽????
邊界限制????
拖拽手柄????
移動端支持??
嵌套滾動處理??
擴展建議
  • 組合API:可結合useDraggable組合式API封裝(Vue3特性)
  • 拖拽回調:通過指令參數暴露@drag-start/@drag-end事件
  • 拖拽限制:支持自定義邊界檢測函數
3、如何設計高性能的動態表單渲染組件?

(1) 分層架構設計

graph TD
A[Schema解析層] --> B[組件映射層]
B --> C[狀態管理層]
C --> D[渲染引擎層]
D --> E[擴展插件層]
  • Schema解析層:支持JSON Schema/自定義DSL描述表單結構
  • 組件映射層:建立字段類型與組件映射關系
  • 狀態管理層:原子化狀態管理 + 響應式更新
  • 渲染引擎層:虛擬滾動 + 差異對比渲染
  • 擴展插件層:校驗、聯動、條件渲染等能力擴展

(2)核心性能優化手段
1)虛擬滾動實現

// 滾動容器
<VirtualScroll itemHeight={80} visibleCount={10}total={1000}
>{(index) => <FormField schema={schemaList[index]}/>}
</VirtualScroll>
  • 僅渲染可視區域內的表單項
  • 滾動時動態計算渲染位置
  • 支持預估高度和動態高度調整

2)狀態管理優化

// 使用Recoil實現原子化狀態
const fieldState = atom({key: 'formField',default: null,effects: [persistState] // 持久化副作用
});// 組件內按需訂閱
const [value, setValue] = useRecoilState(fieldState(id));

3)差異更新算法

function diffUpdate(oldSchema, newSchema) {const patches = [];// 使用JSON-Patch算法生成差異jsonDiff.compare(oldSchema, newSchema, patches);applyPatches(patches); // 局部更新DOM
}

(3)渲染引擎實現
1)組件級緩存

// Vue 實現示例
<template><component :is="getComponent(schema.type)":schema="schema":key="schema.id + schema.version" // 版本控制緩存v-memo="[schema.version]"/>
</template>

2)異步分塊渲染

// 使用requestIdleCallback分批次渲染
function renderChunk(schemas) {let index = 0;function doChunk() {if (index >= schemas.length) return;// 每次渲染50個項const chunk = schemas.slice(index, index + 50);renderItems(chunk);index += 50;requestIdleCallback(doChunk);}doChunk();
}

(4)性能指標與優化驗證
性能測試標準

指標目標值測量工具
首次內容渲染(FCP)<1sLighthouse
輸入響應延遲<50msChrome DevTools
內存占用<100MB/千字段Chrome Memories面板
滾動幀率>=60fpsChrome Rendering面板

優化前后對比

gantt
title 千字段表單性能優化對比
dateFormat  X
axisFormat %s
section 優化前
渲染耗時 : 0, 2500
內存占用 : 0, 350
section 優化后
渲染耗時 : 0, 300
內存占用 : 0, 80

(5)擴展能力設計
1、動態加載策略

// Web Worker 加載復雜校驗規則
const worker = new Worker('validator.worker.js');
worker.postMessage({ rule, value });
worker.onmessage = (e) => updateValidation(e.data);

2、GPU加速渲染

.form-item {will-change: transform, opacity;transform: translateZ(0);
}

3、服務端渲染降級方案

// 服務端生成靜態結構
app.use('/form', (req, res) => {const html = renderToString(<StaticForm schema={schema} />);res.send(html);
});

(六)最佳實踐建議
1、Schema設計規范:

  • 字段ID保持穩定
  • 避免深層嵌套結構
  • 版本化字段配置

2、性能兜底方案:

// 監控渲染時長自動降級
let startTime = Date.now();
renderForm();
if (Date.now() - startTime > 1000) {showLoading();enableDegradedMode(); // 啟用簡化渲染模式
}

3、開發者工具集成:

// 表單性能分析插件
FormDevTools.register({trackRender: true,highlightUpdates: true
});

通過以上架構設計和優化策略,可實現支持萬級字段的動態表單流暢渲染,同時保持開發體驗和可維護性。建議結合具體框架特性進行適配實現,并持續進行性能分析和迭代優化。

4、解釋Vue組件間通信的5種方式及適用場景

1. Props / $emit(父子組件通信)
實現方式:

  • 父 → 子:通過 props 傳遞數據
  • 子 → 父:通過 $emit 觸發事件
<!-- Parent.vue -->
<Child :title="parentTitle" @update="handleUpdate"/><!-- Child.vue -->
<button @click="$emit('update', newValue)">提交</button>

適用場景:

  • 簡單的父子組件數據傳遞
  • 層級不超過3層的組件通信
    優點:Vue官方推薦方式,類型檢查支持完善
    缺點:跨層級通信需要逐層傳遞(Prop drilling)

2. Event Bus(全局事件總線)
實現方式

// eventBus.js
import Vue from 'vue';
export const EventBus = new Vue();// ComponentA.vue
EventBus.$emit('data-change', payload);// ComponentB.vue
EventBus.$on('data-change', callback);

適用場景:

  • 非父子組件間通信(如兄弟組件)
  • 小型項目快速實現跨組件通信
    優點:輕量級、快速實現解耦
    缺點:事件管理混亂,難以維護大型項目
    3. Vuex/Pinia(狀態管理)
    實現方式:
// store.js
export default new Vuex.Store({state: { count: 0 },mutations: { increment(state) { state.count++ } }
});// Component.vue
this.$store.commit('increment');

適用場景:

  • 中大型項目全局狀態管理
  • 需要持久化/可追溯的狀態
  • 多個組件共享復雜業務邏輯
    優點:集中管理、時間旅行調試
    缺點:小型項目引入會增加復雜度

4. provide / inject(依賴注入)
實現方式:

// 祖先組件
export default {provide() {return { theme: this.themeData };}
}// 后代組件
export default {inject: ['theme']
}

適用場景:

  • 跨多層級組件傳遞數據(如主題/配置)
  • 高階組件(HOC)開發
    優點:避免逐層傳遞
    缺點:數據流向不透明,破壞組件獨立性

5、attrs / listeners(透傳屬性和事件)
實現方式:

<!-- 中間組件 -->
<GrandChild v-bind="$attrs" v-on="$listeners"/><!-- 最終組件 -->
<template><div>{{ $attrs.title }}</div>
</template>

適用場景:

  • 創建高階包裝組件
  • 透傳第三方組件原生事件和屬性
    優點:避免手動聲明每個 prop/event
    缺點:Vue3 中 $listeners 被合并到 $attrs

通信方式選型矩陣

場景推薦方案典型示例
直接父子通信Props+$emit表單控件雙向綁定
兄弟組件通信Event Bus / Vuex購物車商品數量同步
跨多層級組件provide/inject主題切換 / 權限注入
復雜狀態共享Vuex / Pinia用戶登錄狀態全局管理
高階組件開發attrs / listeners封裝第三方UI庫組件

性能優化要點
1、避免濫用全局狀態
Pinia/Vuex的狀態變更會觸發所有相關組件更新,需合理劃分模塊
2、使用計算屬性緩存

computed: {filteredList() { /* 復雜計算 */ }
}

3、事件總線及時銷毀

beforeDestroy() {EventBus.$off('event-name');
}

Vue3 新增特性
1、Composition API 響應式傳遞

const sharedState = reactive({ count: 0 });
provide('state', sharedState);

2、Teleport 跨 DOM 通信

<teleport to="#modal-container"><Dialog/>
</teleport>

根據項目規模和組件關系選擇合適的通信方式,避免出現「過度設計」或「通信混亂」兩種極端。對于超過 5 層組件嵌套的場景,建議優先考慮狀態管理方案。

5、如何用Composition API重構 Options API的復雜組件?

**一、重構步驟
1、組件結構分析
**原始Options API結構示例:

export default {data() {return { count: 0,user: null,loading: false}},computed: {doubleCount() { return this.count * 2 }},methods: {async fetchUser() {this.loading = true;this.user = await api.getUser();this.loading = false;}},mounted() {this.fetchUser();}
}

2. 核心邏輯拆分
按功能模塊拆分為組合式函數:

// useCounter.js
export function useCounter(initial = 0) {const count = ref(initial);const doubleCount = computed(() => count.value * 2);return { count, doubleCount };
}// useUser.js
export function useUser() {const user = ref(null);const loading = ref(false);async function fetchUser() {loading.value = true;user.value = await api.getUser();loading.value = false;}onMounted(fetchUser);return { user, loading, fetchUser };
}

3.整合到Setup函數

<script setup>
import { useCounter, useUser } from './composables';const { count, doubleCount } = useCounter();
const { user, loading } = useUser();
</script>

二、關鍵重構技巧
1、響應式數據轉換

Options APIComposition API
data ()ref()/ reactive()
this.property.value訪問
computedcomputed()
watchwatch()/ watchEffect()

2、生命周期映射

Options APIComposition API
beforeCreate無對應,直接寫在setup
created無對應,直接寫在setup
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted

3、方法處理優化

// Options API
methods: {handleClick() { /* ... */ }
}// Composition API
const handleClick = () => { /* ... */ };

三、復雜場景重構示例
1、混合狀態與副作用

原代碼:

export default {data() {return { scrollY: 0 }},mounted() {window.addEventListener('scroll', this.handleScroll);},methods: {handleScroll() {this.scrollY = window.scrollY;}},beforeUnmount() {window.removeEventListener('scroll', this.handleScroll);}
}

重構后:

// useScroll.js
export function useScroll() {const scrollY = ref(0);const handleScroll = () => {scrollY.value = window.scrollY;};onMounted(() => window.addEventListener('scroll', handleScroll));onUnmounted(() => window.removeEventListener('scroll', handleScroll));return { scrollY };
}

2、跨組件邏輯復用
原代碼:

// 多個組件重復相同代碼
export default {data() {return { darkMode: false }},methods: {toggleTheme() {this.darkMode = !this.darkMode;document.body.classList.toggle('dark', this.darkMode);}}
}

重構為可復用邏輯:

// useTheme.js
export function useTheme() {const darkMode = ref(false);const toggleTheme = () => {darkMode.value = !darkMode.value;document.body.classList.toggle('dark', darkMode.value);};return { darkMode, toggleTheme };
}// 組件中使用
const { darkMode, toggleTheme } = useTheme();

四、重構收益對比

指標Options APIComposition API
代碼行數120行80行(減少33%)
功能模塊復用率0%60%邏輯可復用
代碼可讀性邏輯分散在不同選項按功能集中組織
TypeScript支持有限完整類型推斷
Tree-shaking無法優化未使用選項按需導入組合式函數

五、最佳實踐建議
1、漸進式重構策略

  • 優先重構500行以上的復雜組件
  • 使用<script setup>語法糖簡化代碼
  • 保留Options API用于簡單組件
    2、組合式函數設計規范
// 命名規范:use+功能名稱
function usePagination() {}// 單一職責:每個函數只處理一個關注點
function useDataFetching() {}
function useFormValidation() {}// 明確輸入輸出:參數類型化,返回響應式對象
function useSearch(params: SearchParams) {return { results, loading };
}

3、性能優化技巧

// 使用 shallowRef 優化大對象
const bigData = shallowRef({ /* 大型數據集 */ });// 使用 markRaw 跳過代理
const staticConfig = markRaw({ version: 3 });// 合理使用 watchEffect 自動依賴收集
watchEffect(() => {console.log(count.value);
});

通過以上方法,可系統性地將復雜的 Options API 組件改造為更模塊化、更易維護的 Composition API 組件。建議結合 Vue DevTools 的 Composition API 調試功能進行驗證。

三、工程化與性能優化

1、Webpack構建速度優化方案(至少5種)

一、緩存加速方案
1、持久化緩存(Webpack5+)

// webpack.config.js
module.exports = {cache: {type: 'filesystem', // 使用文件系統緩存buildDependencies: {config: [__filename] // 配置文件變更時自動失效緩存}}
};

原理:

  • 將模塊解析、代碼生成結果緩存到磁盤
  • 二次構建時直接復用緩存內容
    效果:冷啟動構建速度提升60% ~ 80%

二、范圍縮小策略
2、精準文件搜索

resolve: {modules: ['node_modules'], // 指定模塊查找目錄extensions: ['.js', '.vue'], /

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

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

相關文章

對稱加密算法——IDEA加密算法

Java IDEA算法詳解 1. 理論背景 IDEA&#xff08;International Data Encryption Algorithm&#xff09;是一種對稱密鑰加密算法&#xff0c;由Xuejia Lai和James Massey于1991年提出。它被設計用于替代DES&#xff08;Data Encryption Standard&#xff09;算法&#xff0c;…

單例模式、構造函數、左值右值

拷貝構造函數 簡單的說就是——用一個對象構造另外一個對象 class Myclass {public:int d0;Myclass(int d_){d d_}; //常用的構造函數Myclass(Myclass c) //拷貝構造函數{d c.d;} }; //對比 class Myclass {public:int d0;Myclass(int d_){d d_}; //常用的構造函數Myclass…

rustdesk遠程桌面自建服務器

首先&#xff0c;我這里用到的是阿里云服務器 centos7版本&#xff0c;win版客戶端。 準備工作 centos7 服務器端文件&#xff1a; https://github.com/rustdesk/rustdesk-server/releases/download/1.1.11-1/rustdesk-server-linux-amd64.zip win版客戶端安裝包&#xff1…

【深度學習】Transformer入門:通俗易懂的介紹

【深度學習】Transformer入門&#xff1a;通俗易懂的介紹 一、引言二、從前的“讀句子”方式三、Transformer的“超級閱讀能力”四、Transformer是怎么做到的&#xff1f;五、Transformer的“多視角”能力六、Transformer的“位置記憶”七、Transformer的“翻譯流程”八、Trans…

用deepseek學大模型03-數學基礎 概率論 最大似然估計(MLE)最大后驗估計(MAP)

https://metaso.cn/s/r4kq4Ni 什么是最大似然估計&#xff08;MLE&#xff09;最大后驗估計&#xff08;MAP&#xff09;&#xff1f;深度學習中如何應用&#xff0c;舉例說明。 好的&#xff0c;我現在需要回答關于最大似然估計&#xff08;MLE&#xff09;和最大后驗估計&…

Socket通訊協議理解及客戶端服務器程序流程

Socket通訊我們可以從以下幾個方面簡單理解 1.Socket是網絡通信中的一項重要技術&#xff0c;它提供了在網絡上進行數據交換的接口。用C#、Java、C等開發語言&#xff0c;都可以開發Socket網絡通信程序。 2.Socket(套接字)是計算機網絡編程中的一種抽象&#xff0c;它允許不同…

《Stable Diffusion繪畫完全指南:從入門到精通的Prompt設計藝術》-配套代碼示例

第一章&#xff1a;模型加載與基礎生成 1.1 基礎模型加載 from diffusers import StableDiffusionPipeline import torch# 加載SD 1.5基礎模型&#xff08;FP32精度&#xff09; pipe StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5",…

【DL】淺談深度學習中的知識蒸餾 | 輸出層知識蒸餾

目錄 一 核心概念與背景 二 輸出層知識蒸餾 1 教師模型訓練 2 軟標簽生成&#xff08;Soft Targets&#xff09; 3 學生模型訓練 三 擴展 1 有效性分析 2 關鍵影響因素 3 變體 一 核心概念與背景 知識蒸餾&#xff08;Knowledge Distillation, KD&#xff09;是一種模…

嵌入式學習第十六天--stdio(二)

文件打開 open函數 #include <fcntl.h> int open(const char *pathname&#xff0c;int flags); int open(const char *pathname&#xff0c;int flags&#xff0c;mode_t mode); 功能: 打開或創建文件 參數: pathname //打開的文件名 flags //操作…

對話智面創始人陶然:一是初心和心態,二是堅持和心力

隨著經濟全球化的加深和市場競爭的日益激烈&#xff0c;企業迅速發展成為了每一個企業家的夢想。然而&#xff0c;要實現企業的快速發展并保持競爭力&#xff0c;企業戰略的人力資源管理起著至關重要的作用。 企業的核心競爭力是“人才”的競爭&#xff0c;無論是研發、銷售、…

mybatis使用typeHandler實現類型轉換

使用mybatis作為操作數據庫的orm框架&#xff0c;操作基本數據類型時可以通過內置的類型處理器完成java數據類型和數據庫類型的轉換&#xff0c;但是對于擴展的數據類型要實現與數據庫類型的轉換就需要自定義類型轉換器完成&#xff0c;比如某個實體類型存儲到數據庫&#xff0…

Qt開發①Qt的概念+發展+優點+應用+使用

目錄 1. Qt的概念和發展 1.1 Qt的概念 1.2 Qt 的發展史&#xff1a; 1.3 Qt 的版本 2. Qt 的優點和應用 2.1 Qt 的優點&#xff1a; 2.2 Qt 的應用場景 2.3 Qt 的應用案例 3. 搭建 Qt 開發環境 3.1 Qt 的開發工具 3.2 Qt SDK 的下載和安裝 3.3 Qt 環境變量配置和使…

mac安裝Pyspark并連接Mysql

安裝Scala, apache-spark, Hadoop brew install scala brew install apache-spark brew install hadoop pip install pyspark注意不要自己另外安裝jdk, 會造成版本對不上報錯。因為安裝apache-spark的過程中會自動安裝openjdk。 配置環境變量 JAVA_HOME/opt/homebrew/Cellar…

【Go語言快速上手】第二部分:Go語言進階之網絡編程

文章目錄 前言&#xff1a;網絡編程一、TCP/UDP 編程&#xff1a;net 包的使用1. TCP 編程1.1 TCP 服務器1.2 TCP 客戶端 2. UDP 編程2.1 UDP 服務器2.2 UDP 客戶端 二、HTTP 編程&#xff1a;net/http 包的使用&#xff0c;編寫 HTTP 服務器和客戶端2.1 HTTP 服務器2.2 HTTP 客…

王炸 用AI+飛書 分解 一鍵生成 項目計劃表模版

效果圖&#xff1a; 各字段設置&#xff1a; 以下是一個使用 AI&#xff08;DeepSeeker&#xff09; 飛書多維表格分解項目待辦模板的示例&#xff0c;你可以根據實際情況進行調整和優化&#xff1a; 列表中需要選擇對象&#xff0c;且選擇輸出結果&#xff08;記得控制字符長度…

從月牙定理看古希臘數學的奇妙突破

文章目錄 每日一句正能量前言古希臘人的 “化圓為方” 之夢&#xff08;一&#xff09;幾何作圖的基本規則&#xff08;二&#xff09;化圓為方問題的起源與發展&#xff08;三&#xff09;化圓為方的意義 月牙面積定理的誕生&#xff08;一&#xff09;希波克拉底的生平與成就…

實戰:vLLM多機多卡部署大模型

兩臺服務器 1. Docker容器中使用GPU 必須確保已安裝并配置 NVIDIA Docker。你可以安裝 nvidia-docker 來確保 GPU 驅動能夠被 Docker 使用 #安裝 nvidia-docker&#xff1a; sudo apt-get install nvidia-docker2#然后重啟 Docker&#xff1a; sudo systemctl restart docke…

LLM中種子(Seed)作用是什么:多樣性

LLM中種子(Seed)作用是什么:多樣性 目錄 LLM中種子(Seed)作用是什么:多樣性作用舉例不同種子的區別設置不同種子的原因在LLM(大語言模型)中,種子(Seed)用于初始化隨機數生成器,發揮著確保結果可重復性的關鍵作用,具體如下: 作用 當大語言模型生成文本時,很多操…

neo4j二進制部署

neo4j二進制部署 下載所需組件 jdk 17 neo4j 5.2.0 配置文件 server.default_listen_address0.0.0.0環境變量 export JAVA_HOME/usr/local/jdk-17.0.13 export CLASSPATH.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar export PATH$…

Win10環境使用零訊ZeroNews內網穿透實現Deepseek對外服務

Win10環境使用零訊ZeroNews內網穿透實現Deepseek對外服務 前言 之前筆者已經在Win10環境搭建好了Ollama、DeepSeek、Open WebUI、Dify等組件&#xff0c;成功實現了私有化部署及內網訪問&#xff1a; https://lizhiyong.blog.csdn.net/article/details/145505686 https://l…