如何進行頁面前端監控

🧑?💻 寫在開頭
點贊 + 收藏 === 學會🤣🤣🤣

前端監控主要分三個方向

前端性能(用戶體驗優化)
異常監控
業務指標跟

下面我來分別介紹三類指標如何獲取

1)前端性能指標:

一、用戶體驗相關的:

頁面加載時間(Page Load Time) :

定義:從用戶請求頁面到頁面完全加載的時間。
測量方法:使用Performance API中的performance.timing對象。

首次內容繪制(First Contentful Paint, FCP) :

定義:瀏覽器從DOM中渲染出第一個內容的時間點。
測量方法:使用PerformanceObserver來監聽paint條目。

最大內容繪制(Largest Contentful Paint, LCP) :

定義:頁面加載過程中最大可見內容的繪制時間。
測量方法:使用PerformanceObserver來監聽largest-contentful-paint條目。

首次輸入延遲(First Input Delay, FID) :

定義:用戶首次與頁面交互(如點擊按鈕)到瀏覽器開始響應交互的時間。
測量方法:使用EventListeners結合PerformanceObserver。

累積布局偏移(Cumulative Layout Shift, CLS) :

定義:頁面布局在加載過程中發生的意外變化的累積得分。
測量方法:使用PerformanceObserver來監聽layout-shift條目。

總阻塞時間(Total Blocking Time, TBT):

定義: TBT 是一個網頁性能指標,用于衡量從首次內容繪制(First Contentful Paint, FCP)到可交互時間(Time to Interactive, TTI)之間,所有超過 50 毫秒的長任務阻塞主線程的時間總和。TBT 反映了頁面在加載過程中用戶交互的延遲情況。
測量方法: 使用PerformanceObserver來監聽longtask條目。通過這種方式,可以捕獲并計算頁面在加載過程中所有長任務的阻塞時間。

交互時間(Time to Interactive, TTI) :

定義:頁面從開始加載到完全可交互的時間。
測量方法:通常通過分析資源加載和長任務來估算。雖然沒有直接的API,但可以結合Long Tasks API和其他指標來推測。

示例代碼
以下是一個簡單的示例代碼,展示如何使用Performance API和PerformanceObserver來測量這些指標:

// 頁面加載時間
window.addEventListener('load', () => {const timing = performance.timing;const pageLoadTime = timing.loadEventEnd - timing.navigationStart;console.log(`Page Load Time: ${pageLoadTime} ms`);
});// 首次內容繪制和最大內容繪制
const observer = new PerformanceObserver((list) => {const entries = list.getEntries();entries.forEach((entry) => {if (entry.name === 'first-contentful-paint') {console.log(`First Contentful Paint: ${entry.startTime} ms`);}if (entry.entryType === 'largest-contentful-paint') {console.log(`Largest Contentful Paint: ${entry.startTime} ms`);}});
});
observer.observe({ type: 'paint', buffered: true });
observer.observe({ type: 'largest-contentful-paint', buffered: true });// 首次輸入延遲
let firstInputDelay = 0;
const fidObserver = new PerformanceObserver((list) => {const entries = list.getEntries();for (const entry of entries) {firstInputDelay = entry.processingStart - entry.startTime;console.log(`First Input Delay: ${firstInputDelay} ms`);}
});
fidObserver.observe({ type: 'first-input', buffered: true });// 累積布局偏移
let cumulativeLayoutShiftScore = 0;
const clsObserver = new PerformanceObserver((list) => {for (const entry of list.getEntries()) {if (!entry.hadRecentInput) {cumulativeLayoutShiftScore += entry.value;console.log(`Cumulative Layout Shift: ${cumulativeLayoutShiftScore}`);}}
});
clsObserver.observe({ type: 'layout-shift', buffered: true });// 長任務
const ttiObserver = new PerformanceObserver((entryList) => {const entries = entryList.getEntries();entries.forEach(entry => {console.log(`Long Task detected: ${entry.startTime} ms, duration: ${entry.duration} ms`);});
});ttiObserver.observe({ entryTypes: ['longtask'] });

總結:上面的指標performance.timing主要是采集一些基礎的時間,目前都是前后端分離的項目參考意義已經不大,除非是ssr和服務端的項目這部分指標有一些參考價值。像最大內容繪制largest-contentful-paint 是一個持續變動的指標,最后計算出最大時間,位移數據也是如此,長任務也是如此持續監聽過程。

二、頁面資源相關

在前端監控中資源監控方面,通常使用的是瀏覽器提供的Performance API。這個 API 提供了一組接口,對于資源監控,具體來說,可以使用以下接口:

PerformanceResourceTiming:

這個接口提供了關于每個資源加載的詳細計時信息。通過它,你可以獲取到資源加載的各個階段的時間,例如 DNS 查詢時間、TCP 連接時間、請求時間、響應時間等。

PerformanceObserver:

這是一個更為通用的接口,可以用來監聽各種性能條目(performance entry)。通過PerformanceObserver,你可以監聽到資源加載事件(resource類型),并在資源加載完成時獲取到相應的PerformanceResourceTiming對象。

以下是一個簡單的示例,展示如何使用PerformanceObserver來監控資源加載:

if ('PerformanceObserver' in window) {const observer = new PerformanceObserver((list) => {const entries = list.getEntriesByType('resource');entries.forEach((entry) => {console.log(`Resource: ${entry.name}`);console.log(`Start Time: ${entry.startTime}`);console.log(`Duration: ${entry.duration}`);console.log(`Initiator Type: ${entry.initiatorType}`);});});observer.observe({ type: 'resource', buffered: true });
}

總結:他可以對頁面所有的資源加載進行監控,比如 js,css,圖片還能夠對xmlhttprequest和fetch監控。也就是說他能夠對接口進行監控,當我們的頁面有一些超長的請求可以單獨識別出來進行報警。

下面是對請求接口的監控:

if ('PerformanceObserver' in window) {const observer = new PerformanceObserver((list) => {const entries = list.getEntriesByType('resource');entries.forEach((entry) => {if (entry.initiatorType === 'xmlhttprequest' || entry.initiatorType === 'fetch') {console.log(`API Request: ${entry.name}`);console.log(`Start Time: ${entry.startTime}`);console.log(`Duration: ${entry.duration}`);console.log(`Fetch Start: ${entry.fetchStart}`);console.log(`Response End: ${entry.responseEnd}`);console.log(`Transfer Size: ${entry.transferSize}`);}});});observer.observe({ type: 'resource', buffered: true });
}

三、其他一些不太重要的監控(不細講)

navigator.getBattery() : 電池監控
Performance Memory API: 內存監控

2)異常監控

一、監聽形式

監聽形式主要是通過捕獲全局錯誤事件來實現。這種方式可以捕獲大部分未處理的異常,并可以將其記錄或發送到服務器進行分析。

1. 使用window.onerror

window.onerror是最傳統的異常捕獲方法,可以捕獲運行時的 JavaScript 錯誤。

window.onerror = function(message, source, lineno, colno, error) {console.error('Error caught:', message, source, lineno, colno, error);// 可以在這里將錯誤信息發送到服務器sendErrorToServer({message,source,lineno,colno,error: error ? error.stack : null});
};function sendErrorToServer(errorInfo) {fetch('/log-error', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify(errorInfo)});
}

2. 使用window.addEventListener(‘error’)

這種方法可以捕獲資源加載錯誤(如圖片、腳本加載失敗)。

window.addEventListener('error', function(event) {console.error('Resource Error:', event);// 處理資源加載錯誤if (event.target instanceof HTMLImageElement) {console.error('Image failed to load:', event.target.src);}// 可以在這里將錯誤信息發送到服務器sendErrorToServer({message: event.message,source: event.filename,lineno: event.lineno,colno: event.colno,error: event.error ? event.error.stack : null});
}, true);

3. 使用window.addEventListener(‘unhandledrejection’)

捕獲未處理的 Promise 異常,此處主要用來捕獲Promise沒有被catch的異常,屬于最后的兜底。

window.addEventListener('unhandledrejection', function(event) {console.error('Unhandled promise rejection:', event.reason);// 可以在這里將錯誤信息發送到服務器sendErrorToServer({message: event.reason ? event.reason.toString() : 'Unknown reason',error: event.reason && event.reason.stack ? event.reason.stack : null});
});

二、主動上報形式

主動上報形式是指在代碼中手動捕獲異常并上報。適用于需要在特定邏輯中捕獲異常的場景。

1. 使用try…catch

在代碼中使用try…catch來捕獲異常,并在catch塊中進行上報。

function riskyOperation() {try {// 執行可能拋出異常的代碼let result = potentiallyFailingFunction();console.log('Operation successful:', result);} catch (error) {console.error('Caught an error:', error);// 在這里上報錯誤sendErrorToServer({message: error.message,error: error.stack});}
}function potentiallyFailingFunction() {// 模擬可能拋出異常的代碼if (Math.random() > 0.5) {throw new Error('Random failure');}return 'Success';
}

2. 集成到應用框架

在現代前端框架(如 React、Vue)中,可以利用框架的錯誤邊界或錯誤處理機制來捕獲和上報異常。

React: 使用 Error Boundary

class ErrorBoundary extends React.Component {constructor(props) {super(props);this.state = { hasError: false };}static getDerivedStateFromError(error) {return { hasError: true };}componentDidCatch(error, errorInfo) {console.error('ErrorBoundary caught an error:', error, errorInfo);// 在這里上報錯誤sendErrorToServer({message: error.message,error: error.stack,componentStack: errorInfo.componentStack});}render() {if (this.state.hasError) {return <h1>Something went wrong.</h1>;}return this.props.children;}
}// 使用 ErrorBoundary 包裹組件
<ErrorBoundary><YourComponent />
</ErrorBoundary>

總結:我本人更加傾向于主動上報形式,因為在現在的開發形式里面,編譯工具和開發工具能夠幫我們避免絕大多數的異常情況,我們的監控往往因為業務邏輯和接口數據返回不對導致對業務的影響,所以主動上報能夠更加準確和清晰的給出異常,這樣利于我們去監控,往往比較多的異常問題不是錯誤導致更多就是接口不符合預期這樣window.onerror形式不太全,最多只能當一個輔助使用。

3、業務指標跟蹤

業務指標跟蹤也是前端監控的一部分,主要用于收集和分析用戶在應用中的行為數據,以幫助理解用戶的使用模式、評估功能效果、優化用戶體驗等。常見的業務指標包括頁面訪問量、點擊事件、用戶停留時間、轉化率等,很多公司都是單獨做,我所在的公司就是這樣,其實原理很簡單就是調用一個接口把想要上報的數據給帶過去就行。

let clickCount = 0;// 獲取按鈕元素
const button = document.getElementById('trackButton');// 為按鈕添加點擊事件監聽器
button.addEventListener('click', () => {clickCount++;console.log('按鈕點擊次數:', clickCount);
});// 頁面卸載時發送數據
window.addEventListener('beforeunload', () => {const data = JSON.stringify({ clickCount });// 使用 sendBeacon 發送數據,確保在頁面卸載時也能發送成功if (navigator.sendBeacon) {navigator.sendBeacon('/track-clicks', data);} else {// 備用方案,使用 fetch 發送數據fetch('/track-clicks', {method: 'POST',headers: {'Content-Type': 'application/json'},body: data});}
});

有個問題,為什么用navigator.sendBeacon去發送數據 ?這就涉及到如何上報數據的問題,下面我具體講下。

一、五種數據上報的形式

XMLHttpRequest:經典的 AJAX 請求方式,用于發送數據到服務器。可以配置為同步或異步請求,但在頁面卸載時可能不可靠。
Fetch API:現代瀏覽器中推薦的方式,用于發送網絡請求。相比XMLHttpRequest,它提供了更簡潔的語法,但在頁面卸載時仍可能會被中斷。
Navigator.sendBeacon:專門用于在頁面卸載時發送數據的 API。sendBeacon是非阻塞的,確保數據在頁面關閉時也能可靠地發送。
Image Ping:通過動態創建圖像對象并設置其src屬性來發送 GET 請求。這種方法常用于簡單的數據上報,不會受到跨域限制,但只能發送少量數據。
WebSocket:用于建立持久連接,實現雙向通信。適合需要實時數據傳輸的場景,但對于簡單的數據上報來說可能過于復雜。

一共有5種形式上報,我來分析下各有什么優劣勢:
其中可以XMLHttpRequest和Fetch沒有什么太大本質的區別屬于一類,他們都是比較常規的上報形式,但是他有個致命問題可能會被中斷,導致數據丟失,特別在頁面跳出的情況,還有就是在請求里面優先級高,在頁面加載的前期當有大量的上報的時候會阻塞頁面的請求看下圖:
在這里插入圖片描述

Image Ping圖片上報,在跨域和調用方式上比較好,但是有個致命的缺點數據量帶不多。
WebSocket我見過的很少,可能在某些場景用的多,但是我很少見到
Navigator.sendBeacon專為頁面卸載設計,確保數據在頁面關閉時發送。非阻塞:不會影響頁面卸載速度。在上圖里面的優先級屬于低,使用簡單,但是有個問題,兼容性有點問題,可以配合fetch使用。他不會應為頁面切換丟數據,調用起來非常方便。

二、上報時機

數據上報的形式可以從不同的角度來分類和理解。一般來說,數據上報主要有以下幾種形式:

實時上報:
數據在產生后立即發送到服務器。這種方式確保數據的實時性,適用于需要即時分析和處理的場景。

批量上報:
數據在客戶端累積到一定數量或滿足特定條件后,再一次性發送到服務器。這種方式可以減少網絡請求次數,適用于對時效性要求不高的場景。

定時上報:
客戶端在固定的時間間隔內發送數據到服務器。這種方式可以平衡實時性和網絡資源的消耗。

頁面卸載上報: 在頁面關閉或卸載時發送數據,通常使用sendBeaconAPI。這種方式確保在用戶離開頁面時也能可靠地將數據發送到服務器。

事件驅動上報:
基于特定事件觸發數據上報,例如用戶點擊按鈕、表單提交等。這種方式適用于需要對特定用戶行為進行監控的場景。

一共有5種形式時機,我來分析下各有什么優劣勢:

實時上報:
優點:
實時性:數據在產生后立即發送,適合需要即時分析的場景。
準確性:可以立即捕捉用戶行為,減少數據丟失的風險。
缺點:
網絡開銷:頻繁發送請求可能增加網絡負擔。
服務器壓力:需要服務器能夠處理高頻率的數據請求。

批量上報:
優點:
減少請求次數:通過合并多條數據減少網絡請求。
提高效率:降低網絡和服務器的負擔。
缺點:
時效性:數據不是實時發送,可能導致分析滯后。
數據丟失風險:如果客戶端崩潰或斷網,未發送的數據可能丟失。

定時上報:
優點:
平衡實時性和效率:通過定時發送,減少頻繁請求。
可控性:可以根據需求調整上報頻率。
缺點:
復雜性:需要實現定時器邏輯。
數據可能不夠實時:與實時上報相比,數據可能有延遲。

頁面卸載上報:
優點:
可靠性:利用sendBeacon確保數據在頁面關閉時發送。
簡單性:不需要復雜的邏輯,只需在頁面卸載時觸發。
缺點:
數據量限制:通常只能發送較小的數據量。
依賴瀏覽器支持:如果瀏覽器不支持sendBeacon,需要備用方案。

事件驅動上報:
優點:
精確性:針對特定用戶行為進行上報,適合精準分析。
靈活性:可以根據業務需求定制上報邏輯。
缺點:
復雜性:需要為每個事件設置監聽器和上報邏輯。
潛在的性能問題:過多的事件監聽可能影響頁面性能。

看你業務需要那種形式,去評估那種形式上報。

我來總結下我在公司遇到的幾種情況:公司H5目前用的最多的就是第一種,但是在客戶端里面是批量,我理解客戶端的形式是最好的,H5的頁面如果在端里面可以借助端的能力去實現批量上報。我們也可以在h5里面頁面卸載的時候去上報,我自己測試過好像有一些兼容問題,最后還是放棄了用的實時上報。

三、最后來個小問題,如何對你的頁面程序方法運行時間進行監控?

頁面程序方法的運行時間進行監控是性能優化的重要一環,可以幫助識別性能瓶頸和優化點。以下是一些常用的方法來監控方法的運行時間:

使用console.time和console.timeEnd:
這是最簡單的方法之一,適用于開發和調試階段。
使用console.time(‘label’)開始計時,console.timeEnd(‘label’)結束計時,并在控制臺輸出運行時間。

console.time('myFunction');myFunction();console.timeEnd('myFunction');

使用performance.now() :
performance.now()提供高精度的時間戳,可以用于精確測量函數的執行時間。

const start = performance.now();myFunction();const end = performance.now();console.log(`myFunction took ${end - start} milliseconds`);

使用PerformanceAPI:
瀏覽器的PerformanceAPI 提供了更全面的性能測量工具,可以記錄和分析多個時間點。
可以使用performance.mark()和performance.measure()來標記和測量代碼片段。

performance.mark('start');myFunction();
performance.mark('end');
performance.measure('myFunction', 'start', 'end');const measures = performance.getEntriesByName('myFunction');console.log(measures[0].duration);

使用第三方庫:

有一些第三方庫可以幫助監控和分析性能,如stats.js或New Relic等。
這些工具通常提供更詳細的性能分析和報告功能。

自定義監控工具:

如果需要更復雜的監控,可以編寫自定義的監控工具,結合performance.now()和日志記錄,將數據發送到服務器進行分析。

目前用的比較多的是performance.mark()因為他是用的比new date提供高精度的時間戳,具體的可以自己去查文檔,我懶得講performance.mark()是 Web Performance API 提供的一個方法,用于在瀏覽器的性能時間線上創建一個標記。這個標記可以幫助開發者測量特定代碼段的執行時間,尤其是在需要精確測量性能的復雜應用中。

用法
創建標記: 使用performance.mark(name)來創建一個標記,其中name是一個字符串,用于標識這個標記。例如:

performance.mark('start');// 執行一些代碼
performance.mark('end');

測量時間: 使用performance.measure(name, startMark, endMark)方法來測量兩個標記之間的時間間隔。name是測量的名稱,startMark和endMark是之前創建的標記。例如:

performance.measure('myMeasure', 'start', 'end');

獲取測量結果: 使用performance.getEntriesByName(name)來獲取測量結果。這個方法返回一個數組,其中包含所有與指定名稱匹配的測量結果。例如:

const measures = performance.getEntriesByName('myMeasure');
measures.forEach((measure) => {console.log(`${measure.name}: ${measure.duration}ms`);
});

我以前用過一個蠢方法就是用mark形式對接口進行打點監控,其實前面見過用資源監控就能完成,后面我為了精準的監控頁面真實的渲染時間,用過mack在頁面渲染完成的時間點去打mark,后面發現有lcp后放棄,但是我認為在有些特殊場景還是能用上,特別在性能優化到后期實在找不到優化點的時候可以對具體的某些方法進行監控優化。

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文檔,大家一起討論學習,一起進步。
在這里插入圖片描述

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

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

相關文章

Ajax技術分析方法全解:從基礎到企業級實踐(2025最新版)

引言 Ajax技術自2005年正式命名以來,已支撐全球83%的Web應用實現異步交互。2025年最新數據顯示,單頁面應用(SPA)的Ajax請求密度已達日均120億次/應用。本文將系統化解析Ajax分析方法論,涵蓋從基礎原理到企業級工程實踐的完整技術棧。 一、Ajax技術架構解構 1.1 核心組件…

git管理github上的repository

1. 首先注冊github并創建一個倉庫&#xff0c;這個很簡單&#xff0c;網上教程也很多&#xff0c;就不展開說了 2. 安裝git&#xff0c;這個也很簡單&#xff0c;不過這里有個問題就是你當前windows的用戶名即&#xff1a;C/Users/xxx 這個路徑不要有中文&#xff0c;因為git …

Windows 下部署 SUNA 項目:虛擬環境嘗試與最終方案

#工作記錄 #回顧總結 本文記錄了在 Windows 系統上&#xff0c;通過 PyCharm 圖形界面&#xff08;盡量減少命令行操作&#xff09;部署 SUNA 項目時&#xff0c;針對不同虛擬環境方案的嘗試過程、遇到的問題以及最終選擇的可行方案&#xff0c;并補充了整體部署思路與推薦。…

無向圖的點、邊雙連通分量

文章目錄 點雙連通分量邊雙連通分量 有向圖的強連通分量&#xff1a;寒假學習筆記【匠心制作&#xff0c;圖文并茂】——1.20拓撲、強連通分量、縮點 點雙連通分量 在這之前&#xff0c;先讓我們了解幾個概念。 割點&#xff1a;刪除一個點和其連出的邊后&#xff0c;原圖會…

第六十二節:深度學習-加載 TensorFlow/PyTorch/Caffe 模型

在計算機視覺領域,OpenCV的DNN(深度神經網絡)模塊正逐漸成為輕量級模型部署的利器。本文將深入探討如何利用OpenCV加載和運行三大主流框架(TensorFlow、PyTorch、Caffe)訓練的模型,并提供完整的代碼實現和優化技巧。 一、OpenCV DNN模塊的核心優勢 OpenCV的DNN模塊自3.3…

Spring @Autowired自動裝配的實現機制

Spring Autowired自動裝配的實現機制 Autowired 注解實現原理詳解一、Autowired 注解定義二、Qualifier 注解輔助指定 Bean 名稱三、BeanFactory&#xff1a;按類型獲取 Bean四、注入邏輯實現五、小結 源碼見&#xff1a;mini-spring Autowired 注解實現原理詳解 Autowired 的…

勝牌?全球成為2026年FIFA世界杯?官方贊助商

勝牌全球將首次與國際足聯&#xff08;FIFA&#xff09;旗艦賽事建立合作關系。 此次贊助恰逢美國首個潤滑油品牌即將迎來160周年之際&#xff0c;其國際擴張步伐正在加快。 在這項全球頂級賽事籌備期間&#xff0c;勝牌全球將通過各種富有創意的零售和體驗活動與球迷互動。 …

YOLOV7改進之融合深淺下采樣模塊(DSD Module)和輕量特征融合模塊(LFI Module)

目錄 一、研究背景? 二. 核心創新點? ?2.1 避免高MAC操作? ?2.2 DSDM-LFIM主干網絡? 2.3 P2小目標檢測分支? ?3. 代碼復現指南? 環境配置 關鍵修改點 ?4. 實驗結果對比? 4.1 VisDrone數據集性能 4.2 邊緣設備部署 4.3 檢測效果可視化 ?5. 應用場景? …

【C/C++】chrono簡單使用場景

chrono使用場景舉例 1 輸出格式化字符串 示例代碼 auto now std::chrono::system_clock::now(); auto t std::chrono::system_clock::to_time_t(now); auto ms std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;std::ostrin…

Med-R1論文閱讀理解-1

論文總結&#xff1a;Med-R1: Reinforcement Learning for Generalizable Medical Reasoning in Vision-Language Models 論文寫了什么&#xff1f; 本文提出了一種名為 Med-R1 的新框架&#xff0c;旨在通過強化學習&#xff08;Reinforcement Learning, RL&#xff09;提升…

京東熱點緩存探測系統JDhotkey架構剖析

熱點探測使用場景 MySQL 中被頻繁訪問的數據 &#xff0c;如熱門商品的主鍵 IdRedis 緩存中被密集訪問的 Key&#xff0c;如熱門商品的詳情需要 get goods$Id惡意攻擊或機器人爬蟲的請求信息&#xff0c;如特定標識的 userId、機器 IP頻繁被訪問的接口地址&#xff0c;如獲取用…

MCU_IO驅動LED

注意事項&#xff1a; 1、亮度要求較高的情況下&#xff0c;不能由IO直接驅動LED MCU_IO引腳輸出的電壓和電流較弱&#xff0c;如果對光的亮度有要求的話&#xff0c;需要使用三極管來驅動。 MCU_IO的電壓一般為3.3V或者5V&#xff0c;輸出電流一般10mA-25mA。 2、不同顏色…

MyBatis 深度解析:高效 Java 持久層框架實踐指南(基于 3.5.10)

一、MyBatis 核心架構與設計哲學 MyBatis 作為半自動 ORM 框架&#xff0c;核心設計目標是在靈活性與開發效率之間取得平衡。與 Hibernate 等全自動 ORM 框架不同&#xff0c;MyBatis 允許開發者完全控制 SQL 編寫&#xff0c;同時通過映射機制減少重復代碼&#xff0c;特別適…

二叉樹(二)

98.驗證二叉樹 中序遍歷二叉樹&#xff0c;每次遍歷存下當前節點的值&#xff0c;遍歷到下一個節點比較&#xff0c;根據二叉搜索樹的特性&#xff0c;左<中<右有&#xff1a; 如果當前值小于或等于上一個的值&#xff0c;說明不是二叉搜索樹 如果當前值大于上一個節點…

解決Vue3+uni-app導航欄高亮自動同步方案

路由跳轉自動識別導航高亮實現方法 以下代碼使用wd-tabbar組件實現路由跳轉時自動同步導航欄高亮狀態&#xff0c;適用于所有的Vue3uni-app項目。 請根據自身使用框架類型完成&#xff0c;也可根據我使用的UI組件進行完成地址如下&#xff1a; Tabbar 標簽欄 | Wot UI &#…

免費論文查重與AI檢測工具推薦

文章目錄 概要一、PaperPass二、PaperYY注意 概要 畢業季&#xff0c;總少不了查重這一步&#xff0c;甚至查 AI 率。推薦兩款免費查重AIGC檢測的工具。 論文免費查重查AI&#xff1a; https://paperpass.com/ https://www.paperyy.com/ 一、PaperPass 網址&#xff1a; ht…

4、ubuntu系統 | 文本和目錄操作函數

1、目錄操作函數 ls(列出目錄內容) 用途:列出指定目錄中的文件和子目錄。語法:ls [選項] [路徑]常用選項: -l:以長格式顯示文件詳細信息(權限、所有者、大小、時間等)。-a:顯示隱藏文件(以.開頭的文件)。-R:遞歸列出子目錄內容。# 列出當前目錄下的所有文件和子目…

C++--范圍for循環詳解

范圍 for 循環是 C11 引入的語法特性&#xff0c;用于簡化遍歷容器或數組元素的過程。它比傳統 for 循環更簡潔安全&#xff0c;特別適合初學者。以下是詳細講解&#xff1a; 基本語法 for (元素類型 變量名 : 容器/數組) {// 循環體&#xff08;使用變量名訪問當前元素&#…

RDMA簡介1之RDMA開發必要性

為了滿足大批量數據的采集、存儲與傳輸需求&#xff0c;越來越多的數據密集型應用如機器學習、雷達、金融風控、航空航天等選擇使用現場可編程邏輯門陣列作為數據采集前端硬件來實現高性能的數據采集系統。FPGA憑借其高靈活性、高并行能力及可高度定制化的特點&#xff0c;能夠…

xmake的簡易學習

文章目錄 1. xmake是什么2. 一個可執行程序3. 一個庫文件4. 遍歷文件用法5. 第三方庫3.1 系統安裝庫3.2 獨立庫 6. 后續 由于前一篇博客的最后說要做一些rknn的優化&#xff0c;其實這個工作很早就完成了&#xff0c;但是我是使用 xmake這個來做我的工程的構建的&#xff0c;不…