流暢如絲:利用requestAnimationFrame優化你的Web動畫體驗

requestAnimationFrame?是前端開發中用于優化動畫性能的 API。它允許瀏覽器在下一次重繪之前執行指定的回調函數,通常用于實現平滑的動畫效果。

1.作用

  1. 優化性能requestAnimationFrame?會根據瀏覽器的刷新率(通常是 60Hz,即每秒 60 幀)來調用回調函數,確保動畫流暢且不浪費資源。

  2. 節省資源:當頁面不可見或最小化時,瀏覽器會自動暫停?requestAnimationFrame?的執行,減少 CPU 和 GPU 的消耗。

  3. 避免丟幀:與?setTimeout?或?setInterval?相比,requestAnimationFrame?能更好地與瀏覽器的渲染周期同步,減少丟幀現象。

2.使用方法

  1. 基本用法

    function animate() {// 動畫邏輯requestAnimationFrame(animate);
    }
    requestAnimationFrame(animate);
  2. 停止動畫

    let animationId;
    function animate() {// 動畫邏輯animationId = requestAnimationFrame(animate);
    }
    animate();// 停止動畫
    cancelAnimationFrame(animationId);

優勢對比

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>requestAnimationFrame vs setTimeout - 點擊開始</title><style>.box {width: 50px;height: 50px;position: relative;top: 0;left: 0;margin-bottom: 20px; /* 增加間距 */}#rafBox {background-color: red;}#timeoutBox {background-color: blue;}.label {font-family: Arial, sans-serif;margin-bottom: 10px;}#startButton {padding: 10px 20px;font-size: 16px;margin-bottom: 20px;cursor: pointer;}</style>
</head>
<body>
<button id="startButton">開始動畫</button><div><div class="label">requestAnimationFrame</div><div id="rafBox" class="box"></div>
</div>
<div><div class="label">setTimeout</div><div id="timeoutBox" class="box"></div>
</div><script>// 增加動畫復雜度:模擬一些計算任務function heavyTask() {let sum = 0;for (let i = 0; i < 1000000; i++) {sum += Math.random();}}// requestAnimationFrame 動畫const rafBox = document.getElementById('rafBox');let rafPosition = 0;let rafStartTime;let rafFrameCount = 0;function rafAnimate() {heavyTask(); // 模擬復雜計算rafPosition += 2; // 每次移動 2pxrafBox.style.left = rafPosition + 'px';rafFrameCount++;if (rafPosition < 600) { // 移動到 600px 時停止requestAnimationFrame(rafAnimate);} else {const rafEndTime = performance.now();console.log(`requestAnimationFrame 完成!用時:${(rafEndTime - rafStartTime).toFixed(2)}ms,幀數:${rafFrameCount}`);}}// setTimeout 動畫const timeoutBox = document.getElementById('timeoutBox');let timeoutPosition = 0;let timeoutStartTime;let timeoutFrameCount = 0;function timeoutAnimate() {heavyTask(); // 模擬復雜計算timeoutPosition += 2; // 每次移動 2pxtimeoutBox.style.left = timeoutPosition + 'px';timeoutFrameCount++;if (timeoutPosition < 600) { // 移動到 600px 時停止setTimeout(timeoutAnimate, 16); // 模擬 60Hz 刷新率} else {const timeoutEndTime = performance.now();console.log(`setTimeout 完成!用時:${(timeoutEndTime - timeoutStartTime).toFixed(2)}ms,幀數:${timeoutFrameCount}`);}}// 點擊按鈕后啟動動畫const startButton = document.getElementById('startButton');startButton.addEventListener('click', () => {// 重置方塊位置rafBox.style.left = '0px';timeoutBox.style.left = '0px';rafPosition = 0;timeoutPosition = 0;// 記錄開始時間rafStartTime = performance.now();timeoutStartTime = performance.now();// 啟動動畫rafAnimate();timeoutAnimate();// 禁用按鈕,防止重復點擊startButton.disabled = true;});
</script>
</body>
</html>
  • 你會看到一個“開始動畫”按鈕,點擊按鈕后:

    • 紅色方塊:使用?requestAnimationFrame,動畫更加流暢。

    • 藍色方塊:使用?setTimeout,動畫可能會出現卡頓。

打開瀏覽器的控制臺(按?F12),可以看到兩者的完成時間和幀數對比

requestAnimationFrame?的兼容封裝?

requestAnimationFrame?在不同瀏覽器中的兼容性確實存在差異,尤其是在一些舊版本的瀏覽器中(如 IE9 及以下)。為了確保代碼的兼容性,我們可以封裝一個通用的?requestAnimationFrame?方法,如果瀏覽器不支持?requestAnimationFrame,則自動降級為?setTimeout

// 兼容性封裝
const requestAnimFrame = (function () {return (window.requestAnimationFrame ||window.webkitRequestAnimationFrame ||window.mozRequestAnimationFrame ||window.oRequestAnimationFrame ||window.msRequestAnimationFrame ||function (callback) {// 如果不支持 requestAnimationFrame,則使用 setTimeout 模擬return window.setTimeout(callback, 1000 / 60); // 模擬 60Hz 刷新率});
})();// 兼容性封裝 cancelAnimationFrame
const cancelAnimFrame = (function () {return (window.cancelAnimationFrame ||window.webkitCancelAnimationFrame ||window.mozCancelAnimationFrame ||window.oCancelAnimationFrame ||window.msCancelAnimationFrame ||function (id) {// 如果不支持 cancelAnimationFrame,則使用 clearTimeoutwindow.clearTimeout(id);});
})();

3.使用方法

啟動動畫

let animationId;function animate() {// 動畫邏輯animationId = requestAnimFrame(animate);
}animate(); // 啟動動畫

停止動畫

cancelAnimFrame(animationId); // 停止動畫

4.完整示例

以下是一個完整的示例,展示如何使用封裝的?requestAnimFrame?方法,并且保留啦優勢對比的藍色方塊,同時也增加了兩個按鈕,可以重復觀看,以感受他們的差異!

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>requestAnimationFrame vs setTimeout 對比</title><style>.box {width: 50px;height: 50px;position: relative;top: 0;left: 0;margin-bottom: 20px; /* 增加間距 */}#rafBox {background-color: red;}#timeoutBox {background-color: blue;}.label {font-family: Arial, sans-serif;margin-bottom: 10px;}button {padding: 10px 20px;font-size: 16px;margin-right: 10px;cursor: pointer;}</style>
</head>
<body>
<button id="startButton">開始動畫</button>
<button id="resetButton">重新執行動畫</button><div><div class="label">requestAnimationFrame</div><div id="rafBox" class="box"></div>
</div>
<div><div class="label">setTimeout</div><div id="timeoutBox" class="box"></div>
</div><script>// 兼容性封裝const requestAnimFrame = (function () {return (window.requestAnimationFrame ||window.webkitRequestAnimationFrame ||window.mozRequestAnimationFrame ||window.oRequestAnimationFrame ||window.msRequestAnimationFrame ||function (callback) {// 如果不支持 requestAnimationFrame,則使用 setTimeout 模擬return window.setTimeout(callback, 1000 / 60); // 模擬 60Hz 刷新率});})();const cancelAnimFrame = (function () {return (window.cancelAnimationFrame ||window.webkitCancelAnimationFrame ||window.mozCancelAnimationFrame ||window.oCancelAnimationFrame ||window.msCancelAnimationFrame ||function (id) {// 如果不支持 cancelAnimationFrame,則使用 clearTimeoutwindow.clearTimeout(id);});})();// requestAnimationFrame 動畫const rafBox = document.getElementById('rafBox');let rafPosition = 0;let rafAnimationId;function rafAnimate() {rafPosition += 2; // 每次移動 2pxrafBox.style.left = rafPosition + 'px';if (rafPosition < 600) { // 移動到 600px 時停止rafAnimationId = requestAnimFrame(rafAnimate);}}// setTimeout 動畫const timeoutBox = document.getElementById('timeoutBox');let timeoutPosition = 0;let timeoutAnimationId;function timeoutAnimate() {timeoutPosition += 2; // 每次移動 2pxtimeoutBox.style.left = timeoutPosition + 'px';if (timeoutPosition < 600) { // 移動到 600px 時停止timeoutAnimationId = setTimeout(timeoutAnimate, 16); // 模擬 60Hz 刷新率}}// 點擊按鈕啟動動畫document.getElementById('startButton').addEventListener('click', () => {// 啟動 requestAnimationFrame 動畫rafAnimate();// 啟動 setTimeout 動畫timeoutAnimate();});// 點擊按鈕重新執行動畫document.getElementById('resetButton').addEventListener('click', () => {// 停止當前動畫cancelAnimFrame(rafAnimationId);clearTimeout(timeoutAnimationId);// 重置方塊位置rafBox.style.left = '0px';timeoutBox.style.left = '0px';rafPosition = 0;timeoutPosition = 0;// 重新啟動動畫rafAnimate();timeoutAnimate();});
</script>
</body>
</html>

5.代碼說明

  1. 兼容性封裝

    • requestAnimFrame?和?cancelAnimFrame?封裝了?requestAnimationFrame?和?cancelAnimationFrame?的兼容性邏輯。

  2. 動畫邏輯

    • 紅色方塊:使用?requestAnimFrame,動畫更加流暢。

    • 藍色方塊:使用?setTimeout,動畫可能會出現卡頓。

  3. 按鈕功能

    • 開始動畫:點擊后同時啟動?requestAnimFrame?和?setTimeout?的動畫。

    • 重新執行動畫:點擊后停止當前動畫,重置方塊位置,并重新啟動動畫。

6.效果展示

7.案例總結

通過這個示例,你可以直觀地看到?requestAnimFrame?和?setTimeout?的差異:

  • requestAnimFrame:動畫流暢,性能更優。

  • setTimeout:動畫可能會出現卡頓。

  • 備注:網上隨便下載的gif錄屏軟件,貌似這種差異不是很明顯,建議自己復制代碼查看,我實際看到的還是很明顯的

?8.性能優化建議

  1. setTimeout?的性能問題

    • 丟幀setTimeout?的時間間隔是固定的(如 16ms 模擬 60Hz),但無法保證與瀏覽器的渲染周期同步,可能導致丟幀或卡頓。

    • 資源浪費:即使頁面不可見或最小化,setTimeout?仍會繼續運行,浪費 CPU 和 GPU 資源。

    • 精度問題setTimeout?的時間精度受系統負載影響,可能導致動畫不流暢。

  2. requestAnimationFrame?的性能優勢

    • 與瀏覽器渲染同步requestAnimationFrame?會在每次瀏覽器重繪前調用回調函數,確保動畫流暢。

    • 節省資源:當頁面不可見或最小化時,requestAnimationFrame?會自動暫停,減少資源消耗。

    • 高精度requestAnimationFrame?的時間戳精度更高,適合高性能動畫。


9.注意事項

  1. 避免頻繁操作 DOM

    • 在動畫回調函數中,盡量減少對 DOM 的頻繁操作(如修改樣式或布局),因為 DOM 操作會觸發重排(reflow)和重繪(repaint),影響性能。

    • 可以通過以下方式優化:

      • 使用?transform?和?opacity?代替?topleft?等屬性,因為前者不會觸發重排。

      • 使用?will-change?屬性提示瀏覽器優化渲染。

  2. 避免阻塞主線程

    • 如果動畫回調函數中有復雜的計算任務(如大量循環或遞歸),可能會導致主線程阻塞,影響動畫流暢性。

    • 可以通過以下方式優化:

      • 將復雜計算任務放到 Web Worker 中執行。

      • 使用?requestIdleCallback?處理低優先級的任務。

  3. 處理動畫停止

    • 使用?cancelAnimationFrame?或?clearTimeout?及時停止動畫,避免不必要的資源消耗。

    • 在頁面不可見時(如切換標簽頁),可以通過?Page Visibility API?檢測頁面狀態,暫停動畫。

  4. 兼容性問題

    • 雖然?requestAnimationFrame?在現代瀏覽器中支持良好,但在舊版本瀏覽器(如 IE9 及以下)中需要降級為?setTimeout

    • 使用兼容性封裝(如前面的代碼)可以解決這個問題。

  5. 動畫幀率控制

    • requestAnimationFrame?的幀率通常是 60Hz,但如果動畫邏輯過于復雜,可能會導致幀率下降。

    • 可以通過時間戳(performance.now())計算幀間隔,動態調整動畫邏輯,確保幀率穩定。

  6. 內存泄漏

    • 如果動畫回調函數中引用了外部變量或 DOM 元素,可能會導致內存泄漏。

    • 確保在動畫停止時,清理不必要的引用。


10.優化建議

  1. 使用硬件加速

    • 通過?transform: translate3d(0, 0, 0)?或?will-change: transform?啟用 GPU 加速,提升動畫性能。

  2. 減少重排和重繪

    • 使用?transform?和?opacity?實現動畫,避免修改?widthheighttopleft?等屬性。

  3. 批量操作 DOM

    • 如果需要修改多個 DOM 元素的樣式,可以使用?DocumentFragment?或?requestAnimationFrame?批量處理,減少重排次數。

  4. 使用 Web Worker

    • 將復雜的計算任務放到 Web Worker 中執行,避免阻塞主線程。

  5. 性能監控

    • 使用?performance.now()?或瀏覽器開發者工具(如 Chrome 的 Performance 面板)監控動畫性能,找出性能瓶頸。


11.優化后的動畫

以下是一個優化后的動畫示例,結合了上述建議:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>三個方塊的性能對比</title><style>body {font-family: Arial, sans-serif;margin: 20px;}.animation-container {margin-bottom: 40px; /* 每個動畫區塊之間的間距 */}.label {font-size: 16px;margin-bottom: 10px; /* 文字與方塊的間距 */}.box {width: 50px;height: 50px;position: relative;left: 0;}#optimizedBox {background-color: red;will-change: transform; /* 啟用硬件加速 */}#unoptimizedRAFBox {background-color: green;}#unoptimizedTimeoutBox {background-color: blue;}button {padding: 10px 20px;font-size: 16px;margin-right: 10px;cursor: pointer;}</style>
</head>
<body><button id="startButton">開始動畫</button><button id="resetButton">重新開始動畫</button><!-- 優化后的動畫 --><div class="animation-container"><div class="label">優化后的動畫(requestAnimationFrame + transform)</div><div id="optimizedBox" class="box"></div></div><!-- 未優化的 requestAnimationFrame 動畫 --><div class="animation-container"><div class="label">未優化的 requestAnimationFrame 動畫(使用 left)</div><div id="unoptimizedRAFBox" class="box"></div></div><!-- 未優化的 setTimeout 動畫 --><div class="animation-container"><div class="label">未優化的 setTimeout 動畫(使用 left)</div><div id="unoptimizedTimeoutBox" class="box"></div></div><script>// 兼容性封裝const requestAnimFrame = (function () {return (window.requestAnimationFrame ||window.webkitRequestAnimationFrame ||window.mozRequestAnimationFrame ||window.oRequestAnimationFrame ||window.msRequestAnimationFrame ||function (callback) {return window.setTimeout(callback, 1000 / 60);});})();const cancelAnimFrame = (function () {return (window.cancelAnimationFrame ||window.webkitCancelAnimationFrame ||window.mozCancelAnimationFrame ||window.oCancelAnimationFrame ||window.msCancelAnimationFrame ||function (id) {window.clearTimeout(id);});})();// 優化后的動畫(requestAnimationFrame + transform)const optimizedBox = document.getElementById('optimizedBox');let optimizedPosition = 0;let optimizedAnimationId;function optimizedAnimate() {optimizedPosition += 2; // 每次移動 2pxoptimizedBox.style.transform = `translateX(${optimizedPosition}px)`; // 使用 transformif (optimizedPosition < 600) { // 移動到 600px 時停止optimizedAnimationId = requestAnimFrame(optimizedAnimate);}}// 未優化的 requestAnimationFrame 動畫(使用 left)const unoptimizedRAFBox = document.getElementById('unoptimizedRAFBox');let unoptimizedRAFPosition = 0;let unoptimizedRAFAnimationId;function unoptimizedRAFAnimate() {unoptimizedRAFPosition += 2; // 每次移動 2pxunoptimizedRAFBox.style.left = unoptimizedRAFPosition + 'px'; // 使用 leftif (unoptimizedRAFPosition < 600) { // 移動到 600px 時停止unoptimizedRAFAnimationId = requestAnimFrame(unoptimizedRAFAnimate);}}// 未優化的 setTimeout 動畫(使用 left)const unoptimizedTimeoutBox = document.getElementById('unoptimizedTimeoutBox');let unoptimizedTimeoutPosition = 0;let unoptimizedTimeoutAnimationId;function unoptimizedTimeoutAnimate() {unoptimizedTimeoutPosition += 2; // 每次移動 2pxunoptimizedTimeoutBox.style.left = unoptimizedTimeoutPosition + 'px'; // 使用 leftif (unoptimizedTimeoutPosition < 600) { // 移動到 600px 時停止unoptimizedTimeoutAnimationId = setTimeout(unoptimizedTimeoutAnimate, 16); // 模擬 60Hz 刷新率}}// 點擊按鈕啟動動畫document.getElementById('startButton').addEventListener('click', () => {// 啟動優化后的動畫optimizedAnimate();// 啟動未優化的 requestAnimationFrame 動畫unoptimizedRAFAnimate();// 啟動未優化的 setTimeout 動畫unoptimizedTimeoutAnimate();});// 點擊按鈕重新開始動畫document.getElementById('resetButton').addEventListener('click', () => {// 停止當前動畫cancelAnimFrame(optimizedAnimationId);cancelAnimFrame(unoptimizedRAFAnimationId);clearTimeout(unoptimizedTimeoutAnimationId);// 重置方塊位置optimizedBox.style.transform = 'translateX(0px)';unoptimizedRAFBox.style.left = '0px';unoptimizedTimeoutBox.style.left = '0px';optimizedPosition = 0;unoptimizedRAFPosition = 0;unoptimizedTimeoutPosition = 0;// 重新啟動動畫optimizedAnimate();unoptimizedRAFAnimate();unoptimizedTimeoutAnimate();});</script>
</body>
</html>

12.效果展示

csdn上gif大小不能超過5M,我這動圖超過5M啦,在線壓縮居然要收費,算了!

大家自己復制源碼感受一下吧!不貼gif圖啦,jpg的對付著看吧!!!

你可以清晰地看到三種實現方式的性能差異:

  1. 優化后的動畫:使用?requestAnimationFrame?和?transform,性能最佳。

  2. 未優化的?requestAnimationFrame?動畫:使用?left,性能稍差。

  3. 未優化的?setTimeout?動畫:使用?left,性能最差。

13.總結

通過優化 DOM 操作、啟用硬件加速、減少重排和重繪,可以顯著提升動畫性能。同時,注意兼容性和資源管理,確保動畫在不同設備和瀏覽器中都能流暢運行。

?

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

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

相關文章

【pytest框架源碼分析五】pytest插件的注冊流程

前文介紹到pytest整體是運用插件來實現其運行流程的。這里仔細介紹下具體過程。 首先進入main方法 def main(args: list[str] | os.PathLike[str] | None None,plugins: Sequence[str | _PluggyPlugin] | None None, ) -> int | ExitCode:"""Perform an i…

IoTDB日志提示Too many open files

問題 時序數據庫 IoTDB 1.3.3 版本 IoTDB 執行查詢操作失敗&#xff0c;日志打印提示 Too many open files。通過命令查看打開文件數&#xff0c;結果如下&#xff1a; [root0002 DataReceiver]# lsof|grep 28347|wc -l DataNode 55444 [root0002 DataReceiver]# lsof|g…

prometheus 添加alertmanager添加dingtalk機器人告警

1、dingtalk創建機器人,目前我們采用加白名單的方式校驗 2、定位到如下圖 test結果如下

C 語 言 --- 操 作 符 2

C 語 言 --- 操 作 符 2 移 位 操 作 符定 義原 碼 補 碼 和 反 碼左 移&#xff08;<<&#xff09;右 移&#xff08;>>&#xff09;算 術 右 移邏 輯 右 移 按 位 與、按 位 或、和 按 位 異 或按 位 與按 位 或按 位 異 或 邏 輯 反 操 作負 值 操 作按 位 取 反…

基于Spring Boot的公司資產網站的設計與實現(LW+源碼+講解)

專注于大學生項目實戰開發,講解,畢業答疑輔導&#xff0c;歡迎高校老師/同行前輩交流合作?。 技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;…

零碳工廠能源管理系統的核心技術與應用實踐

零碳工廠能源管理系統是一種高效的解決方案&#xff0c;旨在優化能源使用并減少碳排放&#xff0c;以幫助工廠實現低碳或零碳的生產目標。以下是該系統的詳細構成和功能&#xff1a; 1. 核心組件 傳感器和監測設備&#xff1a;用于實時監測工廠內的能源使用情況&#xff0c;包…

美攝接入DeepSeek等大模型,用多模態融合重構視頻創作新邊界!

今年以來&#xff0c;DeepSeek憑借其強大的深度推理分析能力&#xff0c;在AI領域掀起新的熱潮。美攝科技快速響應市場需求&#xff0c;迅速接入以DeepSeek、通義千問、商湯、文心一言為代表的大模型&#xff0c;為企業視頻創作生產帶來全新體驗。 傳統視頻創作面臨著同質化、…

JAVA————十五萬字匯總

JAVA語言概述 JAVA語句結構 JAVA面向對象程序設計&#xff08;一&#xff09; JAVA面向對象程序設計&#xff08;二&#xff09; JAVA面向對象程序設計&#xff08;三&#xff09;工具類的實現 JAVA面向對象程序設計&#xff08;四&#xff09;錄入異常處理 JAVA圖形用戶界面設…

力扣熱題100(方便自己復習,自用)

力扣熱題100 1. 兩數之和 - 力扣&#xff08;LeetCode&#xff09; 查找兩數之和是不是等于target也就是我們找到一個數之后&#xff0c;用target將其減掉&#xff0c;再尋找應當對應的元素是什么每找到一個數&#xff0c;我們就將其放在集合中&#xff0c;因為集合中可以去重…

【yolo】yolo訓練報錯,以及解決方案

背景&#xff1a; 剛剛&#xff0c;寫了《【yolo】yolo推理報錯&#xff0c;以及解決方案》&#xff0c;馬上訓練就遇到類似的報錯。 我對我標注的圖像進行了300輪的訓練&#xff0c;但是訓練完300輪后&#xff0c;報錯了。。。 報錯信息 300 epochs completed in 0.085 hou…

vscode/cursor中python運行路徑設置 模塊導入問題

vscode/cursor中python運行路徑設置 ## 文件路徑設置 問題描述 pycharm的項目用cursor運行&#xff0c;出現目錄找不到 后來利用 os.getcwd()&#xff0c;經過打印調試發現是IDE的本身配置問題 pycharm中&#xff0c;os.getcwd()默認打開當前腳本所在目錄 vscode/cursor中…

理解線性動力學中的模態疊加法

線性動力學中的模態疊加方法 模態疊加法是線性動力學中一種有價值的工具&#xff0c;可以有效地確定頻域或時域中的系統響應。對于某些類型的線性動力學分析&#xff0c;有必要使用此方法&#xff0c;因此了解該過程對于獲得準確的結果至關重要。在本博客中&#xff0c;我們將…

報錯 - redis - Unit redis.service could not be found.

報錯&#xff1a; Unit redis.service could not be found.Could not connect to Redis at 127.0.0.1:6379: Connection refused解決方法&#xff1a; 檢查狀態、有必要的話 重新安裝 Linux 上查看狀態 systemctl status redis顯示以下內容&#xff0c;代表正常服務 出現下面…

CMS網站模板定制設計與安全評估

內容概要 現代CMS&#xff08;內容管理系統&#xff09;作為網站建設的核心載體&#xff0c;其模板架構與安全防護體系的協同設計已成為企業數字化轉型的關鍵環節。隨著網絡攻擊向量日益復雜化&#xff0c;基于HTTPS協議的端到端加密部署不僅成為基礎安全配置&#xff0c;更直…

【React】useEffect、useLayoutEffect底層機制

目錄 useEffect不設置依賴設置空數組&#xff0c;無依賴設置多個依賴返回值是一個函數總結useEffect的使用環境useEffect 中發送請求錯誤示例用.then獲取數據在useEffect創建一個函數 總結 useLayoutEffectuseLayoutEffect 和useEffect區別執行時機&#xff1a;瀏覽器渲染的關系…

深度解析學術論文成果評估(Artifact Evaluation):從歷史到現狀

深度解析學術論文成果評估(Artifact Evaluation)&#xff1a;從歷史到現狀 引言 在計算機科學和工程領域的學術研究中&#xff0c;可重復性和可驗證性越來越受到重視。隨著實驗性研究的復雜性不斷增加&#xff0c;確保研究成果可以被其他研究者驗證和構建變得尤為重要。這一需…

VSCode創建VUE項目(四)增加用戶Session管理

將用戶信息存儲或者更新到Session sessionStorage.setItem("userID",loginform.value.username); sessionStorage.setItem(loginTime, Date.now()); 獲取Session信息 const storedUserInfo sessionStorage.getItem(userID); const loginTime sessionStorage.get…

威聯通 后臺可用命令查看Bash

一、查看所有可用命令的方法 列出所有外部命令&#xff08;二進制文件&#xff09; 外部命令通常存放在系統路徑&#xff08;如 /bin, /usr/bin, /sbin, /usr/sbin&#xff09;中&#xff1a; bash ls /bin /usr/bin /sbin /usr/sbin # 直接列出命令目錄&#xff08;結果較長&…

游戲MOD伴隨盜號風險,仿冒網站借“風靈月影”竊密【火絨企業版V2.0】

游戲MOD&#xff08;即游戲修改器&#xff09;是一種能夠對游戲進行修改或增強的程序&#xff0c;因其能夠提升游戲體驗&#xff0c;在玩家群體中擁有一定的市場。然而&#xff0c;這類程序大多由第三方開發者制作&#xff0c;容易缺乏完善的安全保障機制&#xff0c;這就為不法…

Kubernetes Init 容器:實現 Nginx 和 PHP 對 MySQL 的依賴檢查

在設計 Kubernetes Pod 時&#xff0c;如果需要在啟動 Nginx 和 PHP 之前等待 MySQL 啟動完成&#xff0c;可以通過 初始化容器&#xff08;initC&#xff09; 來實現。初始化容器可以用于檢查 MySQL 是否可用&#xff0c;只有在 MySQL 可用后&#xff0c;才會繼續啟動主容器&a…