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

目錄
Suspense 快速入門
讓我們預(yù)加載一些圖像!
實(shí)現(xiàn)
過渡狀態(tài)更新
避免網(wǎng)絡(luò)瀑布
延遲掛起
演示
雜項(xiàng)
首頁 web前端 css教程 用反應(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)簡(jiǎn)單),但是組件告訴 React 它尚未準(zhǔn)備好的方式是拋出一個(gè) Promise。React 將捕獲該 Promise,意識(shí)到組件尚未準(zhǔn)備好,并渲染后備。當(dāng) Promise 解析時(shí),React 將再次嘗試渲染。重復(fù)此過程。是的,我有點(diǎn)過于簡(jiǎ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ù)加載。為了盡可能簡(jiǎn)化操作,讓我們創(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í)間太長(zhǎng),也可能仍然為 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)更新只需等待盡可能長(zhǎng)的時(shí)間)。

這是我的樣子:

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

在我們的后備顯示之前,我們將允許 10 秒鐘過去,這在現(xiàn)實(shí)生活中可能太長(zhǎng)了,但對(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)容,您可能想知道我們是否需要在所有這些渲染發(fā)生之前手動(dòng)預(yù)加載列表中的所有圖像。

事實(shí)證明,無需擔(dān)心,也無需進(jìn)行尷尬的預(yù)加載,因?yàn)?React 對(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é)的挫敗感要好。我還想指出,七秒鐘可能過長(zhǎng)了,但對(duì)于此演示,我假設(shè)用戶可能會(huì)在 DevTools 中降低網(wǎng)絡(luò)速度以更清晰地查看 Suspense 功能,并希望支持這一點(diǎn)。

該演示還有一個(gè)預(yù)緩存圖像復(fù)選框。默認(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)該是純凈的,沒有副作用。React 應(yīng)該能夠多次嘗試重新渲染您的組件,并且(給定相同的初始道具)應(yīng)該從另一端獲得相同的確切狀態(tài)。

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

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請(qǐng)聯(lián)系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脫衣機(jī)

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)鍵資源,尤其是使用引入的樣式表、頭部大量?jī)?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)瀏覽器范圍自動(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