亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

目錄
Suspense 快速入門
讓我們預(yù)加載一些圖像!
實現(xiàn)
過渡狀態(tài)更新
避免網(wǎng)絡(luò)瀑布
延遲掛起
演示
雜項
首頁 web前端 css教學(xué) 用反應(yīng)懸念的預(yù)處理圖像

用反應(yīng)懸念的預(yù)處理圖像

Apr 02, 2025 pm 06:14 PM

Pre-Caching Images with React Suspense

React 的Suspense 功能令人興奮,它即將到來,將使開發(fā)人員能夠輕鬆地讓其組件延遲渲染,直到它們“準備好”,從而帶來更流暢的用戶體驗。 “準備好”在此處可以指許多方面。例如,您的數(shù)據(jù)加載實用程序可以與Suspense 結(jié)合使用,允許在任何數(shù)據(jù)正在傳輸時顯示一致的加載狀態(tài),而無需為每個查詢手動跟蹤加載狀態(tài)。然後,當(dāng)您的數(shù)據(jù)可用且您的組件“準備好”時,它將進行渲染。這是最常與Suspense 一起討論的主題,我之前也寫過關(guān)於它的文章;但是,數(shù)據(jù)加載只是Suspense 可以改善用戶體驗的眾多用例之一。我今天想談?wù)摰牧硪粋€用例是圖像預(yù)加載。

您是否曾經(jīng)製作或使用過一個Web 應(yīng)用,在該應(yīng)用中,在到達屏幕後,您的位置會隨著圖像下載和渲染而發(fā)生抖動和跳躍?我們稱之為內(nèi)容重排,它既令人震驚又令人不快。 Suspense 可以幫助解決這個問題。您知道我說過Suspense 的全部意義在於阻止組件渲染,直到它準備好為止嗎?幸運的是,“準備好”在此處非常開放——出於我們的目的,可以包括“我們需要的已預(yù)加載的圖像”。讓我們看看如何操作!

Suspense 快速入門

在深入探討細節(jié)之前,讓我們快速了解Suspense 的工作原理。它有兩個主要部分。首先是組件掛起的概念。這意味著React 嘗試渲染我們的組件,但它尚未“準備好”。發(fā)生這種情況時,組件樹中最接近的“後備”將進行渲染。我們很快就會看看如何製作後備(這相當(dāng)簡單),但是組件告訴React 它尚未準備好的方式是拋出一個Promise。 React 將捕獲該Promise,意識到組件尚未準備好,並渲染後備。當(dāng)Promise 解析時,React 將再次嘗試渲染。重複此過程。是的,我有點過於簡化了,但這正是Suspense 工作原理的要點,我們將在進行過程中擴展其中一些概念。

Suspense 的第二個部分是引入“過渡”狀態(tài)更新。這意味著我們設(shè)置狀態(tài),但告訴React 狀態(tài)更改可能會導(dǎo)致組件掛起,如果發(fā)生這種情況,則不渲染後備。相反,我們希望繼續(xù)查看當(dāng)前屏幕,直到狀態(tài)更新準備好,此時它將進行渲染。當(dāng)然,React 為我們提供了一個“pending”布爾指示器,讓開發(fā)人員知道此過程正在進行中,以便我們可以提供內(nèi)聯(lián)加載反饋。

讓我們預(yù)加載一些圖像!

首先,我想指出,本文末尾有一個我們正在製作的完整演示。如果您只想跳入代碼,請隨時現(xiàn)在打開演示。它將展示如何將Suspense 與過渡狀態(tài)更新結(jié)合使用來預(yù)加載圖像。這篇文章的其餘部分將逐步構(gòu)建該代碼,並沿途解釋如何以及為什麼。

好的,讓我們開始吧!

我們希望我們的組件掛起,直到所有圖像都已預(yù)加載。為了盡可能簡化操作,讓我們創(chuàng)建一個<suspenseimage></suspenseimage>組件,該組件接收src 屬性,預(yù)加載圖像,處理異常拋出,然後在一切準備就緒時渲染一個<img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174358885649082.png" class="lazy" alt="Pre-Caching Images with React Suspense">在HTML 中使用圖像,但我們也可以使用JavaScript 中的Image()對像以命令式方式創(chuàng)建圖像;此外,我們這樣創(chuàng)建的圖像具有一個onload回調(diào),該回調(diào)在圖像…加載時觸發(fā)。它看起來像這樣:

 const img = new Image();
img.onload = () => {
  // 圖像已加載};

但是我們?nèi)绾螌⑵渑c異常拋出結(jié)合起來呢?如果您像我一樣,您首先可能會想到類似這樣的東西:

 const SuspenseImg = ({ src, ...rest }) => {
  throw new Promise((resolve) => {
    const img = new Image();
    img.onload = () => {
      resolve();
    };
    img.src = src;
  });
  return<img alt="" src="%7Bsrc%7D"> ;
};

當(dāng)然,問題在於這將始終拋出一個Promise。每次React 嘗試渲染<suspenseimg></suspenseimg>實例時,都會創(chuàng)建一個新的Promise,並立即將其拋出。相反,我們只想在圖像加載之前拋出一個Promise。有一句老話,計算機科學(xué)中的每個問題都可以通過添加一層間接性來解決(除了間接性層數(shù)過多的問題),所以讓我們這樣做,並構(gòu)建一個圖像緩存。當(dāng)我們讀取src 時,緩存將檢查它是否已加載該圖像,如果沒有,它將開始預(yù)加載並拋出異常。而且,如果圖像已預(yù)加載,它將只返回true 並讓React 繼續(xù)渲染我們的圖像。

這是我們的<suspenseimage></suspenseimage>組件的樣子:

 export const SuspenseImg = ({ src, ...rest }) => {
  imgCache.read(src);
  return<img  src="%7Bsrc%7D" alt="用反應(yīng)懸念的預(yù)處理圖像" > ;
};

這是我們緩存的最小版本的樣子:

 const imgCache = {
  __cache: {},
  read(src) {
    if (!this.__cache[src]) {
      this.__cache[src] = new Promise((resolve) => {
        const img = new Image();
        img.onload = () => {
          this.__cache[src] = true;
          resolve(this.__cache[src]);
        };
        img.src = src;
      });
    }
    if (this.__cache[src] instanceof Promise) {
      throw this.__cache[src];
    }
    return this.__cache[src];
  }
};

它並不完美,但目前足夠了。讓我們繼續(xù)使用它。

實現(xiàn)

請記住,下面有一個指向完整工作演示的鏈接,因此,如果我在任何特定步驟中移動得太快,請不要絕望。我們將邊走邊解釋。

讓我們從定義我們的後備開始。我們通過在組件樹中放置一個Suspense 標(biāo)記來定義後備,並通過fallback 屬性傳遞我們的後備。任何掛起的組件都將向上搜索最近的Suspense 標(biāo)記,並渲染其後備(但是如果沒有找到Suspense 標(biāo)記,則會拋出錯誤)。一個真正的應(yīng)用程序可能在整個過程中都有許多Suspense 標(biāo)記,為其各個模塊定義特定的後備,但對於此演示,我們只需要一個包裝我們的根應(yīng)用程序的標(biāo)記。

 function App() {
  return (
    <suspense fallback="{<Loading"></suspense> }>
      <showimages></showimages>
    
  );
}

<loading></loading>組件是一個基本的旋轉(zhuǎn)器,但在實際應(yīng)用程序中,您可能希望渲染實際嘗試渲染的組件的某種空殼,以提供更無縫的體驗。

有了這個,我們的<showimages></showimages>組件最終將使用以下內(nèi)容渲染我們的圖像:

<div>
  {images.map((img) => (
    <div key="{img}">
      <suspenseimg alt="" src="%7Bimg%7D"></suspenseimg>
    </div>
  ))}
</div>

在初始加載時,我們的加載旋轉(zhuǎn)器將顯示,直到我們的初始圖像準備好,此時它們將同時顯示,沒有任何交錯的重排卡頓。

過渡狀態(tài)更新

一旦圖像到位,當(dāng)我們加載下一批圖像時,我們希望它們在加載後顯示,當(dāng)然,在它們加載時保持屏幕上的現(xiàn)有圖像。我們使用useTransition鉤子來做到這一點。這將返回一個startTransition函數(shù)和一個isPending布爾值,它指示我們的狀態(tài)更新正在進行中,但已掛起(或者即使它尚未掛起,如果狀態(tài)更新只是花費的時間太長,也可能仍然為true)。最後,當(dāng)調(diào)用useTransition時,您需要傳遞一個timeoutMs值,這是isPending標(biāo)誌可以為true 的最大時間量,之後React 將放棄並渲染後備(請注意, timeoutMs參數(shù)可能會在不久的將來被刪除,當(dāng)更新現(xiàn)有內(nèi)容時,過渡狀態(tài)更新只需等待盡可能長的時間)。

這是我的樣子:

 const [startTransition, isPending] = useTransition({ timeoutMs: 10000 });

在我們的後備顯示之前,我們將允許10 秒鐘過去,這在現(xiàn)實生活中可能太長了,但對於此演示來說是合適的,尤其是在您可能故意在DevTools 中降低網(wǎng)絡(luò)速度以進行實驗時。

以下是如何使用它。當(dāng)您單擊加載更多圖像的按鈕時,代碼如下所示:

 startTransition(() => {
  setPage((p) => p 1);
});

該狀態(tài)更新將使用我的GraphQL 客戶端micro-graphql-react 觸發(fā)新的數(shù)據(jù)加載,該客戶端與Suspense 兼容,在查詢正在進行時將為我們拋出一個Promise。一旦數(shù)據(jù)返回,我們的組件將嘗試渲染,並在我們的圖像預(yù)加載時再次掛起。在所有這些事情發(fā)生的同時,我們的isPending值將為true,這將允許我們在現(xiàn)有內(nèi)容的頂部顯示加載旋轉(zhuǎn)器。

避免網(wǎng)絡(luò)瀑布

您可能想知道React 在圖像預(yù)加載正在進行時如何阻止渲染。使用上面的代碼,當(dāng)我們這樣做時:

 {images.map((img) => (

……以及其中渲染的<suspenseimage></suspenseimage>,React 是否會嘗試渲染第一張圖像,掛起,然後重新嘗試列表,超過第一張圖像(現(xiàn)在在我們的緩存中),然後掛起第二張圖像,然後是第三張、第四張等等。如果您之前閱讀過關(guān)於Suspense 的內(nèi)容,您可能想知道我們是否需要在所有這些渲染髮生之前手動預(yù)加載列表中的所有圖像。

事實證明,無需擔(dān)心,也無需進行尷尬的預(yù)加載,因為React 對其在Suspense 世界中渲染事物的方式相當(dāng)聰明。當(dāng)React 遍歷我們的組件樹時,它不會在遇到掛起時停止。相反,它會繼續(xù)嘗試渲染我們組件樹中的所有其他路徑。因此,是的,當(dāng)它嘗試渲染圖像0 時,將發(fā)生掛起,但React 將繼續(xù)嘗試渲染圖像1 到N,然後才掛起。

您可以通過在加載新圖像集時查看完整演示中的“網(wǎng)絡(luò)”選項卡來查看此操作。您應(yīng)該會看到整個圖像桶立即顯示在網(wǎng)絡(luò)列表中,一個接一個地解析,並且完成後,結(jié)果應(yīng)該顯示在屏幕上。為了真正放大這種效果,您可能希望將網(wǎng)絡(luò)速度降低到“快速3G”。

為了好玩,我們可以通過在React 嘗試渲染我們的組件之前手動從我們的緩存中讀取每個圖像來強制Suspense 遍歷我們的圖像,遍歷組件樹中的每條路徑。

 images.forEach((img) => imgCache.read(img));

我創(chuàng)建了一個演示來說明這一點。如果您同樣在加載新圖像集時查看“網(wǎng)絡(luò)”選項卡,您將看到它們按順序添加到網(wǎng)絡(luò)列表中(但不要在降低網(wǎng)絡(luò)速度的情況下運行此操作)。

延遲掛起

在使用Suspense 時,需要記住一個推論:盡可能在渲染的後期和組件樹的低層掛起。如果您有一些渲染一堆掛起圖像的<imagelist></imagelist>,請確保每個圖像都在其自己的組件中掛起,以便React 可以單獨訪問它,這樣就不會有任何圖像阻塞其他圖像,從而導(dǎo)致瀑布。

此規(guī)則的數(shù)據(jù)加載版本是,數(shù)據(jù)應(yīng)盡可能由實際需要它的組件加載。這意味著我們應(yīng)該避免在一個組件中執(zhí)行以下操作:

 const { data1 } = useSuspenseQuery(QUERY1, vars1);
const { data2 } = useSuspenseQuery(QUERY2, vars2);

我們想要避免這種情況的原因是,查詢一將掛起,然後是查詢二,導(dǎo)致瀑布。如果這根本無法避免,我們將需要在掛起之前手動預(yù)加載這兩個查詢。

演示

這是我承諾的演示。它與我上面鏈接的演示相同。

打開演示如果您運行它並打開開發(fā)工具,請確保取消選中DevTools 網(wǎng)絡(luò)選項卡中顯示的“禁用緩存”框,否則您將破壞整個演示。

該代碼幾乎與我之前顯示的代碼相同。演示中的一個改進是我們的緩存讀取方法具有以下行:

 setTimeout(() => resolve({}), 7000);

很好地預(yù)加載所有圖像,但在現(xiàn)實生活中,我們可能不想無限期地阻止渲染,僅僅是因為一兩張落後的圖像加載緩慢。因此,在一段時間後,我們只需發(fā)出綠燈,即使圖像尚未準備好。用戶將看到一兩張圖像閃爍,但這比忍受軟件凍結(jié)的挫敗感要好。我還想指出,七秒鐘可能過長了,但對於此演示,我假設(shè)用戶可能會在DevTools 中降低網(wǎng)絡(luò)速度以更清晰地查看Suspense 功能,並希望支持這一點。

該演示還有一個預(yù)緩存圖像複選框。默認情況下選中它,但您可以取消選中它以使用普通的<img alt="用反應(yīng)懸念的預(yù)處理圖像" >標(biāo)記替換<suspenseimage></suspenseimage>組件,如果您想將Suspense 版本與“普通React”進行比較(只是不要在結(jié)果出現(xiàn)時選中它,否則整個UI 可能會掛起並渲染後備)。

最後,與CodeSandbox 一樣,某些狀態(tài)有時可能會不同步,因此如果事情開始看起來奇怪或損壞,請點擊刷新按鈕。

雜項

在將此演示放在一起時,我意外地犯了一個巨大的錯誤。我不希望演示的多次運行會因為瀏覽器緩存它已經(jīng)下載的圖像而失去其效果。因此,我使用緩存破壞器手動修改所有URL:

 const [cacheBuster, setCacheBuster] = useState(INITIAL_TIME);

const { data } = useSuspenseQuery(GET_IMAGES_QUERY, { page });
const images = data.allBooks.Books.map(
  (b) => b.smallImage `?cachebust=${cacheBuster}`
);

INITIAL_TIME 在模塊級別(即全局)使用以下行定義:

 const INITIAL_TIME = new Date();

如果您想知道為什麼我沒有這樣做:

 const [cacheBuster, setCacheBuster] = useState( new Date());

……這是因為這會造成可怕的可怕後果。在第一次渲染時,圖像嘗試渲染。緩存導(dǎo)致掛起,React 取消渲染並顯示我們的後備。當(dāng)所有Promise 都已解析後,React 將嘗試重新進行初始渲染,並且我們的初始useState 調(diào)用將重新運行,這意味著:

 const [cacheBuster, setCacheBuster] = useState( new Date());

……將重新運行,並具有新的初始值,導(dǎo)致一組全新的圖像URL,這將再次無限期地掛起。組件將永遠不會運行,並且CodeSandbox 演示會停止運行(這使得調(diào)試變得令人沮喪)。

這似乎是一個由此特定演示的獨特要求引起的奇怪的特殊問題,但有一個更大的教訓(xùn):渲染應(yīng)該是純淨(jìng)的,沒有副作用。 React 應(yīng)該能夠多次嘗試重新渲染您的組件,並且(給定相同的初始道具)應(yīng)該從另一端獲得相同的確切狀態(tài)。

以上是用反應(yīng)懸念的預(yù)處理圖像的詳細內(nèi)容。更多資訊請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Laravel 教程
1597
29
PHP教程
1488
72
CSS教程,用於創(chuàng)建加載旋轉(zhuǎn)器和動畫 CSS教程,用於創(chuàng)建加載旋轉(zhuǎn)器和動畫 Jul 07, 2025 am 12:07 AM

創(chuàng)建CSS加載旋轉(zhuǎn)器的方法有三種:1.使用邊框的基本旋轉(zhuǎn)器,通過HTML和CSS實現(xiàn)簡單動畫;2.使用多個點的自定義旋轉(zhuǎn)器,通過不同延遲時間實現(xiàn)跳動效果;3.在按鈕中添加旋轉(zhuǎn)器,通過JavaScript切換類來顯示加載狀態(tài)。每種方法都強調(diào)了設(shè)計細節(jié)如顏色、大小、可訪問性和性能優(yōu)化的重要性,以提升用戶體驗。

解決CSS瀏覽器兼容性問題和前綴 解決CSS瀏覽器兼容性問題和前綴 Jul 07, 2025 am 01:44 AM

處理CSS瀏覽器兼容性和前綴問題需理解瀏覽器支持差異並合理使用廠商前綴。 1.了解常見問題如Flexbox、Grid支持不一,position:sticky失效,動畫表現(xiàn)不同;2.查閱CanIuse確認特性支持情況;3.正確使用-webkit-、-moz-、-ms-、-o-等廠商前綴;4.推薦使用Autoprefixer自動添加前綴;5.安裝PostCSS並配置browserslist指定目標(biāo)瀏覽器;6.構(gòu)建時自動處理兼容性;7.老項目可用Modernizr檢測特性;8.不必追求所有瀏覽器一致,確

顯示:內(nèi)聯(lián),顯示:塊和顯示:內(nèi)聯(lián)塊之間有什麼區(qū)別? 顯示:內(nèi)聯(lián),顯示:塊和顯示:內(nèi)聯(lián)塊之間有什麼區(qū)別? Jul 11, 2025 am 03:25 AM

Themaindifferencesbetweendisplay:inline,block,andinline-blockinHTML/CSSarelayoutbehavior,spaceusage,andstylingcontrol.1.Inlineelementsflowwithtext,don’tstartonnewlines,ignorewidth/height,andonlyapplyhorizo????ntalpadding/margins—idealforinlinetextstyling

使用CSS剪輯路徑創(chuàng)建自定義形狀 使用CSS剪輯路徑創(chuàng)建自定義形狀 Jul 09, 2025 am 01:29 AM

使用CSS的clip-path屬性可以裁剪元素為自定義形狀,如三角形、圓形缺口、多邊形等,無需依賴圖片或SVG。其優(yōu)勢包括:1.支持circle、ellipse、polygon等多種基本形狀;2.可響應(yīng)式調(diào)整,適配移動端;3.易於動畫化,可結(jié)合hover或JavaScript實現(xiàn)動態(tài)效果;4.不影響佈局流,僅裁剪顯示區(qū)域。常見用法如圓形裁剪clip-path:circle(50pxatcenter)和三角形裁剪clip-path:polygon(50%0%,1000%,00%)。注意

造型與CSS不同訪問的鏈接 造型與CSS不同訪問的鏈接 Jul 11, 2025 am 03:26 AM

設(shè)置訪問過鏈接的樣式能提升用戶體驗,尤其在內(nèi)容密集型網(wǎng)站中幫助用戶更好導(dǎo)航。 1.使用CSS的:visited偽類可定義已訪問鏈接樣式,如顏色變化;2.注意瀏覽器出於隱私限制僅允許修改部分屬性;3.顏色選擇應(yīng)與整體風(fēng)格協(xié)調(diào),避免突兀;4.移動端可能不顯示該效果,建議結(jié)合其他視覺提示如icon輔助標(biāo)識。

如何使用CSS創(chuàng)建響應(yīng)式圖像? 如何使用CSS創(chuàng)建響應(yīng)式圖像? Jul 15, 2025 am 01:10 AM

要使用CSS創(chuàng)建響應(yīng)式圖片,主要可通過以下方法實現(xiàn):1.使用max-width:100%和height:auto讓圖片在保持比例的同時自適應(yīng)容器寬度;2.結(jié)合HTML的srcset和sizes屬性智能加載適配不同屏幕的圖片源;3.利用object-fit和object-position控製圖片裁剪與焦點展示。這些方法共同確保圖片在不同設(shè)備上清晰、美觀地呈現(xiàn)。

什麼是常見的CSS瀏覽器不一致? 什麼是常見的CSS瀏覽器不一致? Jul 26, 2025 am 07:04 AM

不同瀏覽器對CSS解析存在差異,導(dǎo)致顯示效果不一致,主要包括默認樣式差異、盒模型計算方式、Flexbox和Grid佈局支持程度及某些CSS屬性行為不一致。 1.默認樣式處理不一致,解決方法是使用CSSReset或Normalize.css統(tǒng)一初始樣式;2.舊版IE的盒模型計算方式不同,建議統(tǒng)一使用box-sizing:border-box;3.Flexbox和Grid在邊緣情況或舊版本中表現(xiàn)有差異,應(yīng)多測試並使用Autoprefixer;4.某些CSS屬性行為不一致,需查閱CanIuse並提供降級

揭開CSS單元的神秘面紗:PX,EM,REM,VW,VH比較 揭開CSS單元的神秘面紗:PX,EM,REM,VW,VH比較 Jul 08, 2025 am 02:16 AM

CSS單位的選擇取決於設(shè)計需求和響應(yīng)式要求。 1.px用於固定尺寸,適合精確控制但缺乏彈性;2.em是相對單位,受父元素影響易導(dǎo)致級聯(lián)問題,rem則基於根元素更穩(wěn)定,適合全局縮放;3.vw/vh基於視口大小,適合響應(yīng)式設(shè)計,但需注意極端屏幕下的表現(xiàn);4.選擇時應(yīng)根據(jù)是否需要響應(yīng)式調(diào)整、元素層級關(guān)係及視口依賴程度來決定,合理搭配使用可提升佈局靈活性與維護性。

See all articles