国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目錄
Suspense 快速入門
讓我們預(yù)加載一些圖像!
實(shí)現(xiàn)
過渡狀態(tài)更新
避免網(wǎng)絡(luò)瀑布
延遲掛起
演示
雜項(xiàng)
首頁 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ā)人員能夠輕鬆地讓其組件延遲渲染,直到它們“準(zhǔn)備好”,從而帶來更流暢的用戶體驗(yàn)。 “準(zhǔn)備好”在此處可以指許多方面。例如,您的數(shù)據(jù)加載實(shí)用程序可以與Suspense 結(jié)合使用,允許在任何數(shù)據(jù)正在傳輸時(shí)顯示一致的加載狀態(tài),而無需為每個(gè)查詢手動(dòng)跟蹤加載狀態(tài)。然後,當(dāng)您的數(shù)據(jù)可用且您的組件“準(zhǔn)備好”時(shí),它將進(jìn)行渲染。這是最常與Suspense 一起討論的主題,我之前也寫過關(guān)於它的文章;但是,數(shù)據(jù)加載只是Suspense 可以改善用戶體驗(yàn)的眾多用例之一。我今天想談?wù)摰牧硪粋€(gè)用例是圖像預(yù)加載。

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

Suspense 快速入門

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

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

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

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

好的,讓我們開始吧!

我們希望我們的組件掛起,直到所有圖像都已預(yù)加載。為了盡可能簡化操作,讓我們創(chuàng)建一個(gè)<suspenseimage></suspenseimage>組件,該組件接收src 屬性,預(yù)加載圖像,處理異常拋出,然後在一切準(zhǔn)備就緒時(shí)渲染一個(gè)<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()對(duì)像以命令式方式創(chuàng)建圖像;此外,我們這樣創(chuàng)建的圖像具有一個(gè)onload回調(diào),該回調(diào)在圖像…加載時(shí)觸發(fā)。它看起來像這樣:

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

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

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

實(shí)現(xiàn)

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

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

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

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

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

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

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

過渡狀態(tài)更新

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

這是我的樣子:

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

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

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

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

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

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

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

 {images.map((img) => (

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

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

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

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

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

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

延遲掛起

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

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

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

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

演示

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

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

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

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

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

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

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

雜項(xiàng)

在將此演示放在一起時(shí),我意外地犯了一個(gè)巨大的錯(cuò)誤。我不希望演示的多次運(yùn)行會(huì)因?yàn)闉g覽器緩存它已經(jīng)下載的圖像而失去其效果。因此,我使用緩存破壞器手動(dò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 在模塊級(jí)別(即全局)使用以下行定義:

 const INITIAL_TIME = new Date();

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

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

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

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

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

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

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

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

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

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

Dreamweaver CS6

Dreamweaver CS6

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

SublimeText3 Mac版

SublimeText3 Mac版

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

什麼是'渲染障礙CSS”? 什麼是'渲染障礙CSS”? Jun 24, 2025 am 12:42 AM

CSS會(huì)阻塞頁面渲染是因?yàn)闉g覽器默認(rèn)將內(nèi)聯(lián)和外部CSS視為關(guān)鍵資源,尤其是使用引入的樣式表、頭部大量內(nèi)聯(lián)CSS以及未優(yōu)化的媒體查詢樣式。 1.提取關(guān)鍵CSS並內(nèi)嵌至HTML;2.延遲加載非關(guān)鍵CSS通過JavaScript;3.使用media屬性優(yōu)化加載如打印樣式;4.壓縮合併CSS減少請(qǐng)求。建議使用工具提取關(guān)鍵CSS,結(jié)合rel="preload"異步加載,合理使用media延遲加載,避免過度拆分與復(fù)雜腳本控制。

外部與內(nèi)部CSS:最好的方法是什麼? 外部與內(nèi)部CSS:最好的方法是什麼? Jun 20, 2025 am 12:45 AM

thebestapphachforcssdepprodsontheproject'sspefificneeds.forlargerprojects,externalcsSissBetterDuoSmaintoMaintainability andReusability; forsMallerProjectsorsingle-pageApplications,InternaltCsmightBemoresobleable.InternalCsmightBemorese.it.it'sclucialtobalancepopryseceneceenceprodrenceprodrenceNeed

我的CSS必須在較低的情況下嗎? 我的CSS必須在較低的情況下嗎? Jun 19, 2025 am 12:29 AM

否,CSSDOESNOTHAVETOBEINLOWERCASE.CHOMENDENS,使用flowercaseisrecommondendendending:1)一致性和可讀性,2)避免使用促進(jìn)性技術(shù),3)潛在的Performent FormanceBenefits,以及4)RightCollaboraboraboraboraboraboraboraboraboraboraboraboraboraboraboraboraborationWithInteams。

CSS案例靈敏度:了解重要的 CSS案例靈敏度:了解重要的 Jun 20, 2025 am 12:09 AM

cssismostlycaseminemintiment,buturlsandfontfamilynamesarecase敏感。 1)屬性和valueslikeColor:紅色; prenotcase-sensive.2)urlsmustmustmatchtheserver'server'scase,例如

什麼是AutoPrefixer,它如何工作? 什麼是AutoPrefixer,它如何工作? Jul 02, 2025 am 01:15 AM

Autoprefixer是一個(gè)根據(jù)目標(biāo)瀏覽器範(fàn)圍自動(dòng)為CSS屬性添加廠商前綴的工具。 1.它解決了手動(dòng)維護(hù)前綴易出錯(cuò)的問題;2.通過PostCSS插件形式工作,解析CSS、分析需加前綴的屬性、依配置生成代碼;3.使用步驟包括安裝插件、設(shè)置browserslist、在構(gòu)建流程中啟用;4.注意事項(xiàng)有不手動(dòng)加前綴、保持配置更新、非所有屬性都加前綴、建議配合預(yù)處理器使用。

什麼是CSS計(jì)數(shù)器? 什麼是CSS計(jì)數(shù)器? Jun 19, 2025 am 12:34 AM

csscounterscanautomationallymentermentermentections和lists.1)usecounter-ensettoInitializize,反插入式發(fā)芽,andcounter()orcounters()

CSS:何時(shí)重要(何時(shí)不)? CSS:何時(shí)重要(何時(shí)不)? Jun 19, 2025 am 12:27 AM

在CSS中,選擇器和屬性名不區(qū)分大小寫,而值、命名顏色、URL和自定義屬性則區(qū)分大小寫。 1.選擇器和屬性名不區(qū)分大小寫,例如background-color和Background-Color相同。 2.值中的十六進(jìn)制顏色不區(qū)分大小寫,但命名顏色區(qū)分大小寫,如red有效而Red無效。 3.URL區(qū)分大小寫,可能導(dǎo)致文件加載問題。 4.自定義屬性(變量)區(qū)分大小寫,使用時(shí)需注意大小寫一致。

什麼是圓錐級(jí)函數(shù)? 什麼是圓錐級(jí)函數(shù)? Jul 01, 2025 am 01:16 AM

theconic-Gradient()functionIncsscreatesCircularGradientsThatRotateColorStopSaroundAcentralPoint.1.IsidealForPieCharts,ProgressIndicators,colordichers,colorwheels和decorativeBackgrounds.2.itworksbysbysbysbydefindefingincolordefingincolorstopsatspecificains off.

See all articles