整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          「原生案例」如何在JavaScript中實現(xiàn)實時搜索功能

          載說明:原創(chuàng)不易,未經(jīng)授權(quán),謝絕任何形式的轉(zhuǎn)載

          在當(dāng)今充滿活力的網(wǎng)絡(luò)開發(fā)領(lǐng)域中,實現(xiàn)強大的搜索功能是一個關(guān)鍵特性,可以極大地增強用戶體驗,并使瀏覽大型數(shù)據(jù)集變得輕松自如。如果您想要為您的網(wǎng)站或網(wǎng)絡(luò)應(yīng)用程序添加實時搜索功能,那么您來對地方了。本篇全面的文章將探討使用JavaScript實現(xiàn)實時搜索功能的方方面面。

          無論您是經(jīng)驗豐富的開發(fā)人員還是剛開始編碼之旅的新手,本文旨在為您提供一般編碼知識和工具,以便將實時搜索功能融入到您的項目中。通過本指南的學(xué)習(xí),您將對相關(guān)概念和技術(shù)有扎實的理解,從而能夠創(chuàng)建響應(yīng)式和交互式的搜索功能,實現(xiàn)用戶輸入時動態(tài)更新的效果。

          為了有效地跟隨本指南,建議您對HTML、CSS和JavaScript的基本知識有扎實的理解。熟悉DOM操作和事件處理將有助于我們深入了解實現(xiàn)細節(jié)。然而,即使您對JavaScript或Web開發(fā)相對較新,本指南的結(jié)構(gòu)也旨在提供清晰的解釋和逐步的說明,使其適用于不同技能水平的學(xué)習(xí)者。

          現(xiàn)在,為了更好地理解這個功能的重要性和使用方法,我們將創(chuàng)建一個非常基本的項目作為示例;更具體地說,一個如下所示的電影應(yīng)用程序:

          您可以在這里查看實時實施情況。

          https://search-movies-live.netlify.app/

          在這個項目中,我們將利用實時搜索功能來搜索電影數(shù)據(jù)庫中的電影列表。我知道你迫不及待地想要開始了,我們馬上就會開始。但首先,讓我們更多地了解一下實時搜索功能及其重要性。

          實時搜索功能的重要性

          在當(dāng)今數(shù)字化的環(huán)境中,實時搜索功能變得至關(guān)重要,滿足了高效信息檢索的需求,提升了整體用戶體驗。通過在用戶輸入時實時更新搜索結(jié)果,實時搜索提供即時反饋,便于快速獲取相關(guān)信息。這種動態(tài)交互式的搜索功能帶來了許多好處,使用戶和網(wǎng)站所有者受益。

          • 改進的用戶體驗:實時搜索通過提供無縫和直觀的搜索過程顯著提升了用戶體驗。當(dāng)用戶開始輸入查詢時,搜索結(jié)果會實時更新,提供即時反饋,消除了手動提交或頁面刷新的需求。這種互動性節(jié)省了用戶寶貴的時間和精力,從而實現(xiàn)了更高效和令人滿意的搜索體驗。
          • 更快的信息檢索:通過實時搜索,用戶可以快速找到所需的信息,無需瀏覽多個頁面或等待搜索結(jié)果加載。隨著用戶的輸入,搜索結(jié)果立即縮小范圍,顯示相關(guān)建議,無需輸入完整的搜索查詢。這種速度和響應(yīng)能夠使用戶在傳統(tǒng)搜索方法所需時間的一小部分內(nèi)找到他們想要的內(nèi)容。
          • 增加參與度和轉(zhuǎn)化率:實時搜索的無縫和響應(yīng)性特性鼓勵用戶更積極地與網(wǎng)站或網(wǎng)絡(luò)應(yīng)用程序互動。提供即時反饋和相關(guān)建議可以保持用戶的參與度,減少跳出率和沮喪感的可能性。這種增加的參與度可以提高轉(zhuǎn)化率,因為用戶更有可能進一步探索網(wǎng)站并將他們的搜索意圖轉(zhuǎn)化為行動。
          • 增強的過濾和細化功能:實時搜索功能通常包括額外的功能,如過濾器、建議和自動完成選項。這些功能幫助用戶細化搜索并縮小結(jié)果范圍,使他們能夠找到他們想要的內(nèi)容。通過提供這些工具,實時搜索不僅改善了搜索體驗,還幫助用戶發(fā)現(xiàn)可能一開始沒有考慮到的相關(guān)內(nèi)容或產(chǎn)品。
          • 網(wǎng)站所有者的寶貴見解:實時搜索功能可以為用戶行為和偏好提供寶貴的見解。通過分析搜索查詢和模式,網(wǎng)站所有者可以更好地了解用戶的需求,識別流行趨勢或話題,并在內(nèi)容創(chuàng)作、產(chǎn)品提供或用戶界面改進方面做出明智決策。這些見解使網(wǎng)站所有者能夠根據(jù)用戶需求量身定制自己的產(chǎn)品,從而提高客戶滿意度和業(yè)務(wù)增長。

          設(shè)置HTML結(jié)構(gòu)

          既然我們已經(jīng)完全了解了實時搜索功能以及它的重要性,那么讓我們深入探討一下如何在您自己的項目中實現(xiàn)這個功能。

          首先,讓我們建立項目的結(jié)構(gòu)。對于這個項目,我們只需要三個文件,即HTML、CSS和JavaScript文件。

          現(xiàn)在讓我們開始設(shè)置項目的HTML結(jié)構(gòu):在HTML文件中,我們首先需要包含我們的標(biāo)準(zhǔn)HTML樣板,包括鏈接和腳本到我們的CSS和JS文件中:

          <!doctype html>
          <html lang="en">
           <head>
             <meta charset="UTF-8" />
             <meta name="viewport" content="width=device-width, initial-scale=1.0" />
             <link rel="stylesheet" href="./live-search.css" />
             <title> </title>
           </head>
           <body>
             <script src="./live-search.js"></script>
           </body>
          </html>

          現(xiàn)在在 body 標(biāo)簽中,我們包含了 header 和 main 語義標(biāo)簽。在 header 標(biāo)簽內(nèi),我們設(shè)置了項目的標(biāo)題部分,這里只包括應(yīng)用程序的名稱和一個視頻圖標(biāo)。

          <header>
           <ion-icon name="videocam"></ion-icon>
           <h1>Search Movies</h1>
          </header>

          在我們繼續(xù)講解 main 標(biāo)簽之前,在 body 標(biāo)簽的末尾,讓我們包含所需的 script 標(biāo)簽,以便能夠使用這些圖標(biāo):

          <script
           type="module"
           src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"
          ></script>
          <script
           nomodule
           src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"
          ></script>

          您可以在Ionicons網(wǎng)站上找到這些圖標(biāo)。

          https://ionic.io/ionicons

          現(xiàn)在,在 main 標(biāo)簽內(nèi),我們將包含我們的第一個 div 標(biāo)簽,這將是我們的搜索欄容器,在其中,我們放置我們的搜索輸入標(biāo)簽和一個搜索圖標(biāo):

          <div id="search-container">
           <ion-icon name="search-outline"></ion-icon>
           <input type="search" id="search-bar" placeholder="Search movies..." />
          </div>

          然后,我們將在這個“div”下面創(chuàng)建另一個 div 標(biāo)簽。這將包含所有電影數(shù)據(jù)的結(jié)果:

          <div id="results-container"></div>

          我們暫時將其留空,因為其內(nèi)容將在JavaScript部分生成。

          最后,在 main 標(biāo)簽中,我們將包含一個 p 標(biāo)簽。這個標(biāo)簽只是為了在稍后向用戶顯示錯誤或空消息的響應(yīng)。

          <p id="movie-unavailable-txt"></p>

          這就是HTML文件的全部內(nèi)容,整體代碼應(yīng)該是這樣的:

          <!doctype html>
          <html lang="en">
           <head>
             <meta charset="UTF-8" />
             <meta http-equiv="X-UA-Compatible" content="IE=edge" />
             <meta name="viewport" content="width=device-width, initial-scale=1.0" />
             <link rel="stylesheet" href="./live-search.css" />
             <title>Live Search Functionality</title>
           </head>
           <body>
             <header>
               <ion-icon name="videocam"></ion-icon>
               <h1>Search Movies</h1>
             </header>
          
             <main>
               <div id="search-container">
                 <ion-icon name="search-outline"></ion-icon>
                 <input type="search" id="search-bar" placeholder="Search movies..." />
               </div>
          
               <div id="results-container"></div>
          
               <p id="movie-unavailable-txt"></p>
             </main>
          
             <script src="./live-search.js"></script>
             <script
               type="module"
               src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"
             ></script>
             <script
               nomodule
               src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"
             ></script>
           </body>
          </html>

          既然我們已經(jīng)完成了項目的HTML結(jié)構(gòu)的實現(xiàn),那么讓我們給頁面添加一些樣式。

          為頁面添加樣式

          在這個部分,我們將為頁面的各個部分添加基本的樣式。所以讓我們開始吧。首先,讓我們?yōu)轫撁娴恼w部分添加一些常規(guī)樣式:

          html{
           scroll-behavior: smooth;
           background-color: #111;
           color: whitesmoke;
          }
          
          *{
           margin: 0;
           padding: 0;
           box-sizing: border-box;
          }
          

          現(xiàn)在讓我們?yōu)轭^部部分及其內(nèi)容添加一些樣式:

          header{
           display: flex;
           justify-content: center;
           padding: 25px;
           letter-spacing: 2px;
           position: sticky;
           top: 0%;
           z-index: 2;
           border-bottom: 2px solid ;
           background-color: black;
           text-shadow: 3px 3px 5px #fd1d6b;   
           box-shadow: 10px 10px 20px -10px #fd1d6b; 
          }
          
          header > ion-icon{
           color:#fd1d6b;
           font-size: 60px;
           position: absolute;
           left: 5%;
          }

          接下來,我們開始對搜索容器及其內(nèi)容進行樣式設(shè)置:

          #search-container{
           display: flex;
           justify-content: center;
           padding: 20px;
           margin-bottom: 20px;
           position: sticky;
           top: 100px;
          }
          
          #search-bar{
           border: none;
           width: 60%;
           padding: 15px;
           padding-left: 40px;
           border-radius: 15px;
           font-size: 15px;
          }
          
          #search-container>ion-icon{
           color: gray;
           position: relative;
           left: 30px;
           top: 13px;
           z-index: 3;
           font-size: 19px;
          }

          之后,我們繼續(xù)設(shè)計將來從電影數(shù)據(jù)庫中獲取的所有電影的 results-container 的樣式

          #results-container{
           border-right: 5px solid #fd1d6b;
           border-left: 5px solid #fd1d6b;     
           border-radius: 25px;
           display: flex;
           justify-content: center;
           flex-wrap: wrap;
           width: 90vw;
          }

          接下來,我們在 movie-unavailable-txt 中添加樣式,同時將 display 設(shè)置為 none ,因為我們暫時不希望它可見

          #movie-unavailable-txt{
           text-align: center;
           letter-spacing: 2px;
           display: none;
           margin-top: 15%;
           text-shadow: 3px 3px 5px #fd1d6b;
          }
          

          接下來,我們將為一些尚未聲明但將通過JavaScript創(chuàng)建的元素添加一些樣式。這是電影卡片,將顯示電影的詳細信息,包括電影圖片和標(biāo)題:

          .movie-cards{
           padding: 25px;
           max-width: 250px;
           border-radius: 15px;
           display: grid;
           place-items: center;
           box-shadow: 1px 1px 20px -1px #fd1d6b ;
           margin: 50px;
          }
          
          .title{
           margin: 20px auto;
           text-align: center;
           font-size: 1.2rem;
           text-shadow: 3px 3px 5px #fd1d6b;  
          }
          
          .date{
           margin-top: 15px;
           font-size: 0.8rem;
           text-shadow: 3px 3px 5px #fd1d6b;  
          }
          
          .movie-image{
           width: 90%;
           max-width: 400px;
           object-fit: contain;
           border-radius: 5px;
          }

          既然我們已經(jīng)完成了頁面的樣式,那么讓我們繼續(xù)進行最有趣和最重要的部分,即Javascript的實現(xiàn)。

          向電影數(shù)據(jù)庫API發(fā)送異步搜索請求

          在本節(jié)中,我們將調(diào)用我們選擇的電影數(shù)據(jù)庫API來填充我們的頁面,展示各種電影。在這種情況下,我將使用RapidAPI Hub中的IMDb Top 100 Movies免費電影API。在API頁面中,我們選擇要使用的特定數(shù)據(jù),然后復(fù)制頁面右側(cè)提供的javascript(fetch)代碼,如下所示:

          https://rapidapi.com/rapihub-rapihub-default/api/imdb-top-100-movies

          首先,在您使用API之前,請先訂閱它(無需信用卡),以便為您生成一個API密鑰。您可以在API的定價頁面上進行訂閱。

          繼續(xù),我們進入我們的空的JavaScript文件,并將我們復(fù)制的代碼粘貼進去:

          const url = "https://imdb-top-100-movies.p.rapidapi.com/";
          const options = {
           method: "GET",
           headers: {
             "X-RapidAPI-Key": "YOUR GENERATED API KEY",
             "X-RapidAPI-Host": "imdb-top-100-movies.p.rapidapi.com",
           },
          };
          
          try {
           const response = await fetch(url, options);
           const result = await response.text();
           console.log(result);
          } catch (error) {
           console.error(error);
          }

          既然我們已經(jīng)將電影數(shù)據(jù)庫的API引入到我們的項目中,我們可以使用它的數(shù)據(jù)了。接下來,我們將聲明一些我們需要的變量,并將它們放在我們復(fù)制的代碼中 try 塊的上方。

          const searchBar = document.getElementById("search-bar");
          const resultsContainer = document.getElementById("results-container");
          const movieUnavailableTxt = document.getElementById("movie-unavailable-txt");
          let movieList;
          let searchValue;
          let searchedMovies;

          我們正在接近剛剛創(chuàng)建的這些變量的目的,堅持住。

          接下來,我們對復(fù)制的代碼中的 try 塊進行一些更改,因為我們希望將其與我們的項目完全集成。所以首先,我們需要創(chuàng)建一個異步函數(shù):

          const fetchMovies = async () => {
           // try catch block goes in here.
          };

          在這個函數(shù)內(nèi)部,我們將放置從我們復(fù)制的代碼中的整個 try catch 塊,以便我們可以進行異步API調(diào)用。

          在 try 塊內(nèi),我們將刪除 console.log(result) 行,并將 result 變量更改為先前聲明的 movieList 變量,并將同一行中的 response.text() 更改為 response.json() 。這樣,我們從API調(diào)用中接收到的數(shù)據(jù)將以 JSON 格式呈現(xiàn),這是我們所需的。因此,該行現(xiàn)在應(yīng)該是這樣的

          movieList = await response.json();

          現(xiàn)在我們已經(jīng)成功從API中獲取了電影并返回了我們的數(shù)據(jù)集,我們需要將這些數(shù)據(jù)填充到我們的頁面中。為此,我們將調(diào)用 renderMovies() 函數(shù),并將參數(shù)設(shè)置為從API調(diào)用中獲取的數(shù)據(jù)。不用擔(dān)心,我們很快就會創(chuàng)建這個函數(shù):

          renderMovies(movieList);

          現(xiàn)在讓我們創(chuàng)建 renderMovies 函數(shù),這個函數(shù)剛剛在 fetchMovies() 函數(shù)中調(diào)用過,這個函數(shù)將用于創(chuàng)建動態(tài)電影卡片模板,我們之前在CSS文件中設(shè)置了樣式,模板中的每個元素的內(nèi)容都將設(shè)置為從API獲取的數(shù)據(jù),這樣我們就可以使用相同的模板渲染不同的電影。然后,我們將把電影卡片放在 resultsContainer 元素中。每次調(diào)用函數(shù)時,我們需要清除 resultsContainer ,并將 moviesUnavailableTxt 設(shè)置為 display="none" ,因為我們希望在渲染電影到頁面時文本不可見,同時清除 moviesReturnedOnSearch 數(shù)組,然后將從搜索輸入字段返回的新數(shù)據(jù)設(shè)置到其中。

          const renderMovies = (movies) => {
           resultsContainer.innerHTML = ""; // Clear the existing movies
           movieUnavailableTxt.style.display = "none"; // Hide the "No movies found" message
           moviesReturnedOnSearch = []; // Clear the movies returned on search array
          
           movies.forEach((movie) => {
             resultsContainer.innerHTML += `
               <div class="movie-cards">
                 <img src="${movie.image}" alt="movie image" class="movie-image" />
                 <h2 class="title">${movie.title}</h2>
                 <p class="plot">${movie.description}</p>
                 <p class="date">${movie.year}</p>
               </div>
             `;
          
             moviesReturnedOnSearch.push(movie); // Add the movies that are a result to the search input value
           });
          };

          捕捉用戶輸入并實時顯示電影搜索結(jié)果

          現(xiàn)在我們已經(jīng)將所有電影數(shù)據(jù)加載到我們的頁面上,接下來是真正有趣的部分,我們要實現(xiàn)實時搜索功能,所以,不浪費時間,讓我們開始吧。

          為了捕獲用戶輸入,我們將使用 input 事件監(jiān)聽器,并將其鏈接到 searchBar 元素。我們使用這個特定的事件監(jiān)聽器,因為它可以捕獲搜索框內(nèi)的每一個活動,包括輸入、清除和粘貼,這正是我們想要的。所以讓我們繼續(xù)創(chuàng)建它:

          searchBar.addEventListener("input", (event) => {
           // live functionality code
          });

          好的,現(xiàn)在我們已經(jīng)將事件監(jiān)聽器鏈接到搜索欄,以便監(jiān)聽用戶的任何輸入。在第二個參數(shù)中,我們添加了事件處理程序,這是每當(dāng)搜索欄有輸入時將被調(diào)用的函數(shù)。現(xiàn)在,在該函數(shù)內(nèi)部,我們將編寫處理實時搜索的代碼。

          在搜索功能中,我們需要做的第一件事是編輯從用戶那里獲取到的輸入值,并將其轉(zhuǎn)換為全小寫,同時去除任何不必要的空格:

          searchValue = event.target.value.trim().toLowerCase();

          在那之后,我們繼續(xù)根據(jù)用戶的搜索輸入,通過檢查用戶輸入的電影標(biāo)題是否包含在 movieList 數(shù)據(jù)中的任何電影標(biāo)題中,并將電影標(biāo)題設(shè)置為小寫以與用戶輸入匹配,來在頁面上按標(biāo)題篩選電影

          const filteredMovies = movieList.filter( (movie) => movie.title.toLowerCase().includes(searchValue) );

          接下來,我們將通過再次調(diào)用 renderMovies() 函數(shù),并將參數(shù)設(shè)置為 filtered Movies 變量的值,來顯示與用戶在搜索欄中輸入的字符匹配的電影標(biāo)題的實時搜索結(jié)果。

          renderMovies(filteredMovies);

          通過調(diào)用此函數(shù),它僅將與搜索欄中鍵入的字符匹配的電影渲染到頁面上,使用函數(shù)中提供的電影卡片模板,同時將每個匹配的電影添加到 moviesReturnedOnSearch 數(shù)組中,以便我們可以跟蹤每個字符輸入的匹配搜索值的電影數(shù)量。在處理空響應(yīng)錯誤時,這將非常有用,現(xiàn)在我們將進入這個部分。

          處理空或錯誤響應(yīng)

          在任何應(yīng)用程序中,有效處理空或錯誤的響應(yīng)至關(guān)重要。在這種情況下,這些情景可能發(fā)生在搜索查詢沒有結(jié)果或API請求存在問題時。

          處理錯誤或空響應(yīng)時,向用戶提供清晰的反饋是至關(guān)重要的。話雖如此,由于這是一個相對簡單的應(yīng)用程序,我們不必過多擔(dān)心錯誤,因為我們只需要處理由API引起的錯誤。例如,API服務(wù)可能暫時不可用,或者應(yīng)用程序可能剛剛超過了請求限制。為了處理這個錯誤,我們只需要將 movieUnavailableTxt 元素的 display 設(shè)置為 block ,并將 innerHTML 設(shè)置為向用戶顯示錯誤消息,并將其放置在 fetchMovies() 函數(shù)的 catch 塊中。因此,現(xiàn)在 catch 塊的代碼如下所示:

          catch (error) {
           movieUnavailableTxt.innerHTML = 'An error occurred while fetching movies. <br /> Please try again later.';
           movieUnavailableTxt.style.display = "block";
           console.error(error);
          }

          現(xiàn)在我們已經(jīng)處理完錯誤響應(yīng),接下來我們要處理空響應(yīng)。如果用戶搜索的電影與頁面上的任何電影都不匹配,我們需要向用戶提示所搜索的電影不可用。為了做到這一點,首先我們需要檢查之前聲明的 moviesReturnedOnSearch 數(shù)組的內(nèi)容,如果數(shù)組的長度小于或等于0,我們將設(shè)置 movieUnavailableTxt 元素的 display 為 block ,并將 innerHTML 設(shè)置為空響應(yīng)消息,如下所示:

          if (moviesReturnedOnSearch.length <= 0) {
           movieUnavailableTxt.innerHTML = "OOPS! <br/><br/> Movie not available";
           movieUnavailableTxt.style.display = "block"; // Show the "No movies found" message if no movies match the search
          }

          我們將把這個 if 塊放在 searchBar 事件處理程序的閉合括號之前。

          通過緩存提高搜索性能

          在使用API實現(xiàn)實時搜索功能時,提高性能的一種有效技術(shù)是緩存。緩存涉及存儲先前獲取的搜索結(jié)果,并在再次請求相同的搜索查詢時重復(fù)使用它們。這可以顯著減少API調(diào)用的次數(shù),有助于防止超過API的請求限制,并改善搜索功能的響應(yīng)速度以及網(wǎng)站的加載時間。

          要在我們的項目中實現(xiàn)緩存,首先,我們需要確定哪些項目需要被緩存,而在這種情況下,那將是 movieList 變量的值,它是我們從 fetch API請求中得到的 JSON 格式的數(shù)據(jù)。通過緩存這個項目,我們將能夠在頁面重新加載時使用API的數(shù)據(jù),而無需進行額外的 fetch 請求。但是對于這個項目,我們將為我們的緩存數(shù)據(jù)設(shè)置一個過期時間,為6小時,這意味著頁面每6小時只會進行一次API請求,而不是在每次頁面重新加載時都進行請求。這樣做是為了保持頁面的數(shù)據(jù)新鮮和最新,同時將API請求保持在最低限度。

          回到我們的代碼中,現(xiàn)在我們需要將數(shù)據(jù)存儲在瀏覽器的本地存儲中,但為了做到這一點,我們需要首先將其轉(zhuǎn)換為一個 string ,并設(shè)置一個鍵名,用于在本地存儲中標(biāo)識數(shù)據(jù)。讓我們將其設(shè)置為 movieData ,如下所示:

          localStorage.setItem("moviedata", JSON.stringify(movieList));

          接下來我們需要將當(dāng)前日期和時間存儲在本地存儲中:

          localStorage.setItem("cacheTimestamp", Date.now());

          這將當(dāng)前日期和時間以毫秒為單位存儲,鍵名為 cacheTimeStamp 。

          我們將把這兩行代碼放在 try 塊的 fetchMovies() 函數(shù)中,就在 movieList 變量的下方。

          接下來,在 fetchMovies() 函數(shù)之外,緊接著 renderMovies() 函數(shù)的下方,我們將把緩存數(shù)據(jù)的過期時間設(shè)置為6小時(以毫秒為單位)

          const expirationDuration = 21600000; // 6 hours in milliseconds

          之后,我們需要取回之前在本地存儲中設(shè)置的 cacheTimestamp

          const cacheTimestamp = localStorage.getItem("cacheTimestamp");

          現(xiàn)在,我們將檢查緩存數(shù)據(jù)是否已過期或不可用,這意味著它尚未被存儲。如果是這種情況,我們將通過調(diào)用 fetch 函數(shù)向API發(fā)出新的請求。另一方面,如果緩存數(shù)據(jù)存在且尚未過期,我們將使用它來渲染頁面上的電影,而不是再次發(fā)出新的 fetch 請求。我們通過檢索緩存的電影數(shù)據(jù)并將其解析回 JSON 格式來使用,然后將參數(shù)設(shè)置為從緩存中獲取的數(shù)據(jù),調(diào)用 render 函數(shù)來實現(xiàn)這一點。

          // Check if cache has expired or data is not available
          if (
           !cacheTimestamp ||
           Date.now() - parseInt(cacheTimestamp) > expirationDuration
          ) {
           // Cache expired or data not available, fetch movies again
           fetchMovies();
          } else {
           // Use cached movie data
           movieList = JSON.parse(localStorage.getItem("moviedata"));
           renderMovies(movieList);
          }

          在 if 語句中, !cacheTimestamp 檢查 cacheTimestamp 變量是否為假值,意味著它可以是 null 、 undefined 、0、 false 或空字符串。如果 cacheTimestamp 為假,表示沒有存儲現(xiàn)有緩存時間戳。 Date.now() - parseInt(cacheTimestamp) 計算當(dāng)前時間戳與解析的 cacheTimestamp 的整數(shù)值之間的時間差。簡單來說,這就是說:“當(dāng)前時間的值減去我們之前存儲在緩存中的時間的值,是否大于我們設(shè)置的過期時間?如果是,就從API中重新獲取電影數(shù)據(jù);如果不是,就使用緩存的數(shù)據(jù)。”

          就是這樣,這就是我們?nèi)绾螌?shù)據(jù)緩存起來以便重復(fù)使用,而不是在每次用戶輸入或每次頁面重新加載時發(fā)起請求。正如你所看到的,這將極大地優(yōu)化應(yīng)用程序的性能,因為它可以防止由于網(wǎng)絡(luò)慢而導(dǎo)致的電影渲染緩慢。

          我們已經(jīng)完成了我們的小電影應(yīng)用程序中展示實時搜索功能的所有特性的實現(xiàn)。以下是該應(yīng)用程序的整體JavaScript代碼:

          const url = "https://imdb-top-100-movies.p.rapidapi.com/";
          const options = {
           method: "GET",
           headers: {
             "X-RapidAPI-Key": "Your Generated API Key",
             "X-RapidAPI-Host": "imdb-top-100-movies.p.rapidapi.com",
           },
          };
          
          const searchBar = document.getElementById("search-bar");
          const resultsContainer = document.getElementById("results-container");
          const movieUnavailableTxt = document.getElementById("movie-unavailable-txt");
          let movieList;
          let searchValue;
          let moviesReturnedOnSearch;
          
          // Function to fetch movies from the API
          const fetchMovies = async () => {
           try {
             const response = await fetch(url, options);
             movieList = await response.json();
          
             // Storing the Movie Data in browser storage
             localStorage.setItem("moviedata", JSON.stringify(movieList));
             localStorage.setItem("cacheTimestamp", Date.now()); // Update cache timestamp
          
             // Render the movies on the page
             renderMovies(movieList);
           } catch (error) {
             movieUnavailableTxt.innerHTML =
               "An error occurred while fetching movies. <br /> Please try again later.";
             movieUnavailableTxt.style.display = "block";
             console.error(error);
           }
          };
          
          // Function to render movies on the page
          const renderMovies = (movies) => {
           resultsContainer.innerHTML = ""; // Clear the existing movies
           movieUnavailableTxt.style.display = "none"; // Hide the "No movies found" message
           moviesReturnedOnSearch = []; // Clear the movies returned on search array
          
           movies.forEach((movie) => {
             resultsContainer.innerHTML += `
               <div class="movie-cards">
                 <img src="${movie.image}" alt="movie image" class="movie-image" />
                 <h2 class="title">${movie.title}</h2>
                 <p class="plot">${movie.description}</p>
                 <p class="date">${movie.year}</p>
               </div>
             `;
          
             moviesReturnedOnSearch.push(movie); // Add the movies that are a result to the search input value
           });
          };
          
          const cacheTimestamp = localStorage.getItem("cacheTimestamp");
          const expirationDuration = 21600000; // 6 hours in milliseconds
          
          // Check if cache has expired or data is not available
          if (
           !cacheTimestamp ||
           Date.now() - parseInt(cacheTimestamp) > expirationDuration
          ) {
           // Cache expired or data not available, fetch movies again
           fetchMovies();
          } else {
           // Use cached movie data
           movieList = JSON.parse(localStorage.getItem("moviedata"));
           renderMovies(movieList);
          }
          
          // Event listener and handler for search bar input
          searchBar.addEventListener("input", (event) => {
           searchValue = event.target.value.trim().toLowerCase();
          
           // Filter movies based on search input
           const filteredMovies = movieList.filter((movie) =>
             movie.title.toLowerCase().includes(searchValue),
           );
          
           // Render the filtered movies on the page
           renderMovies(filteredMovies);
          
           if (moviesReturnedOnSearch.length <= 0) {
             movieUnavailableTxt.style.display = "block"; // Show the "No movies found" message if no movies match the search
           }
          });

          結(jié)論

          在本指南中,我們探討了使用API在JavaScript中實現(xiàn)實時搜索功能的方法。按照所述步驟,您可以創(chuàng)建一個動態(tài)搜索體驗,當(dāng)用戶在搜索欄中輸入時,可以提供實時結(jié)果。

          通過在您的網(wǎng)站上實現(xiàn)實時搜索功能,您可以增強用戶參與度,提高您的網(wǎng)站或應(yīng)用程序的可用性。用戶將欣賞能夠快速方便地找到相關(guān)信息,而無需重新加載頁面。

          通過這個指南所獲得的知識,您已經(jīng)具備了在JavaScript中有效實現(xiàn)實時搜索功能的能力。擁抱動態(tài)搜索的力量,創(chuàng)造一個無縫的用戶體驗,給人留下深刻的印象。

          由于文章內(nèi)容篇幅有限,今天的內(nèi)容就分享到這里,文章結(jié)尾,我想提醒您,文章的創(chuàng)作不易,如果您喜歡我的分享,請別忘了點贊和轉(zhuǎn)發(fā),讓更多有需要的人看到。同時,如果您想獲取更多前端技術(shù)的知識,歡迎關(guān)注我,您的支持將是我分享最大的動力。我會持續(xù)輸出更多內(nèi)容,敬請期待。

          來了~歡迎轉(zhuǎn)發(fā)、收藏,記得點個贊唄。^_^

          無論當(dāng)前 JavaScript 代碼是內(nèi)嵌還是在外鏈文件中,頁面的下載和渲染都必須停下來等待腳本執(zhí)行完成。JavaScript 執(zhí)行過程耗時越久,瀏覽器等待響應(yīng)用戶輸入的時間就越長。瀏覽器在下載和執(zhí)行腳本時出現(xiàn)阻塞的原因在于,腳本可能會改變頁面或 JavaScript 的命名空間,它們對后面頁面內(nèi)容造成影響。一個典型的例子就是在頁面中使用document.write()。例如清單 1。

          清單 1 JavaScript 代碼內(nèi)嵌示例

          當(dāng)瀏覽器遇到<script>標(biāo)簽時,當(dāng)前 HTML 頁面無從獲知 JavaScript 是否會向<p> 標(biāo)簽添加內(nèi)容,或引入其他元素,或甚至移除該標(biāo)簽。因此,這時瀏覽器會停止處理頁面,先執(zhí)行 JavaScript代碼,然后再繼續(xù)解析和渲染頁面。同樣的情況也發(fā)生在使用 src 屬性加載 JavaScript的過程中,瀏覽器必須先花時間下載外鏈文件中的代碼,然后解析并執(zhí)行它。在這個過程中,頁面渲染和用戶交互完全被阻塞了。

          1.腳本位置

          HTML 4 規(guī)范指出 <script> 標(biāo)簽可以放在 HTML 文檔的<head>或<body>中,并允許出現(xiàn)多次。Web 開發(fā)人員一般習(xí)慣在 <head> 中加載外鏈的 JavaScript,接著用 <link> 標(biāo)簽用來加載外鏈的 CSS 文件或者其他頁面信息。例如清單 2。

          清單 2 低效率腳本位置示例

          然而這種常規(guī)的做法卻隱藏著嚴(yán)重的性能問題。在清單 2 的示例中,當(dāng)瀏覽器解析到 <script> 標(biāo)簽(第 4 行)時,瀏覽器會停止解析其后的內(nèi)容,而優(yōu)先下載腳本文件,并執(zhí)行其中的代碼,這意味著,其后的 styles.css 樣式文件和<body>標(biāo)簽都無法被加載,由于<body>標(biāo)簽無法被加載,那么頁面自然就無法渲染了。因此在該 JavaScript 代碼完全執(zhí)行完之前,頁面都是一片空白。圖 1 描述了頁面加載過程中腳本和樣式文件的下載過程。

          圖 1 JavaScript 文件的加載和執(zhí)行阻塞其他文件的下載

          我們可以發(fā)現(xiàn)一個有趣的現(xiàn)象:第一個 JavaScript 文件開始下載,與此同時阻塞了頁面其他文件的下載。此外,從 script1.js 下載完成到 script2.js 開始下載前存在一個延時,這段時間正好是 script1.js 文件的執(zhí)行過程。每個文件必須等到前一個文件下載并執(zhí)行完成才會開始下載。在這些文件逐個下載過程中,用戶看到的是一片空白的頁面。

          從 IE 8、Firefox 3.5、Safari 4 和 Chrome 2 開始都允許并行下載 JavaScript 文件。這是個好消息,因為<script>標(biāo)簽在下載外部資源時不會阻塞其他<script>標(biāo)簽。遺憾的是,JavaScript 下載過程仍然會阻塞其他資源的下載,比如樣式文件和圖片。盡管腳本的下載過程不會互相影響,但頁面仍然必須等待所有 JavaScript 代碼下載并執(zhí)行完成才能繼續(xù)。因此,盡管最新的瀏覽器通過允許并行下載提高了性能,但問題尚未完全解決,腳本阻塞仍然是一個問題。

          由于腳本會阻塞頁面其他資源的下載,因此推薦將所有<script>標(biāo)簽盡可能放到<body>標(biāo)簽的底部,以盡量減少對整個頁面下載的影響。例如清單 3

          清單 3 推薦的代碼放置位置示例

          這段代碼展示了在 HTML 文檔中放置<script>標(biāo)簽的推薦位置。盡管腳本下載會阻塞另一個腳本,但是頁面的大部分內(nèi)容都已經(jīng)下載完成并顯示給了用戶,因此頁面下載不會顯得太慢。

          這是優(yōu)化 JavaScript 的首要規(guī)則:將腳本放在底部。

          2.組織腳本

          由于每個<script>標(biāo)簽初始下載時都會阻塞頁面渲染,所以減少頁面包含的<script>標(biāo)簽數(shù)量有助于改善這一情況。這不僅針對外鏈腳本,內(nèi)嵌腳本的數(shù)量同樣也要限制。瀏覽器在解析 HTML 頁面的過程中每遇到一個<script>標(biāo)簽,都會因執(zhí)行腳本而導(dǎo)致一定的延時,因此最小化延遲時間將會明顯改善頁面的總體性能。

          這個問題在處理外鏈 JavaScript 文件時略有不同。考慮到 HTTP 請求會帶來額外的性能開銷,因此下載單個 100Kb 的文件將比下載 5 個 20Kb 的文件更快。也就是說,減少頁面中外鏈腳本的數(shù)量將會改善性能

          通常一個大型網(wǎng)站或應(yīng)用需要依賴數(shù)個 JavaScript 文件。您可以把多個文件合并成一個,這樣只需要引用一個<script>標(biāo)簽,就可以減少性能消耗。文件合并的工作可通過離線的打包工具或者一些實時的在線服務(wù)來實現(xiàn)。

          需要特別提醒的是,把一段內(nèi)嵌腳本放在引用外鏈樣式表的<link>之后會導(dǎo)致頁面阻塞去等待樣式表的下載。這樣做是為了確保內(nèi)嵌腳本在執(zhí)行時能獲得最精確的樣式信息。因此,建議不要把內(nèi)嵌腳本緊跟在<link>標(biāo)簽后面。

          3.無阻塞的腳本

          減少 JavaScript 文件大小并限制 HTTP 請求數(shù)在功能豐富的 Web 應(yīng)用或大型網(wǎng)站上并不總是可行。Web 應(yīng)用的功能越豐富,所需要的 JavaScript 代碼就越多,盡管下載單個較大的 JavaScript 文件只產(chǎn)生一次 HTTP 請求,卻會鎖死瀏覽器的一大段時間。為避免這種情況,需要通過一些特定的技術(shù)向頁面中逐步加載 JavaScript 文件,這樣做在某種程度上來說不會阻塞瀏覽器。

          無阻塞腳本的秘訣在于,在頁面加載完成后才加載 JavaScript 代碼。這就意味著在 window 對象的 onload事件觸發(fā)后再下載腳本。有多種方式可以實現(xiàn)這一效果。

          3.1延遲加載腳本

          HTML 4 為<script>標(biāo)簽定義了一個擴展屬性:defer。Defer 屬性指明本元素所含的腳本不會修改 DOM,因此代碼能安全地延遲執(zhí)行。defer 屬性只被 IE 4 和 Firefox 3.5 更高版本的瀏覽器所支持,所以它不是一個理想的跨瀏覽器解決方案。在其他瀏覽器中,defer 屬性會被直接忽略,因此<script>標(biāo)簽會以默認(rèn)的方式處理,也就是說會造成阻塞。然而,如果您的目標(biāo)瀏覽器支持的話,這仍然是個有用的解決方案。清單 4 是一個例子

          清單 4 defer 屬性使用方法示例

          <script type="text/javascript" src="script1.js" defer></script>

          帶有 defer 屬性的<script>標(biāo)簽可以放置在文檔的任何位置。對應(yīng)的 JavaScript 文件將在頁面解析到<script>標(biāo)簽時開始下載,但不會執(zhí)行,直到 DOM 加載完成,即onload事件觸發(fā)前才會被執(zhí)行。當(dāng)一個帶有 defer 屬性的 JavaScript 文件下載時,它不會阻塞瀏覽器的其他進程,因此這類文件可以與其他資源文件一起并行下載。

          任何帶有 defer 屬性的<script>元素在 DOM 完成加載之前都不會被執(zhí)行,無論內(nèi)嵌或者是外鏈腳本都是如此。清單 5 的例子展示了defer屬性如何影響腳本行為:

          清單 5 defer 屬性對腳本行為的影響

          這段代碼在頁面處理過程中彈出三次對話框。不支持 defer 屬性的瀏覽器的彈出順序是:"defer"、"script"、"load"。而在支持 defer 屬性的瀏覽器上,彈出的順序則是:"script"、"defer"、"load"。請注意,帶有 defer 屬性的<script>元素不是跟在第二個后面執(zhí)行,而是在 onload 事件被觸發(fā)前被調(diào)用。

          如果您的目標(biāo)瀏覽器只包括 Internet Explorer 和 Firefox 3.5,那么 defer 腳本確實有用。如果您需要支持跨領(lǐng)域的多種瀏覽器,那么還有更一致的實現(xiàn)方式。

          HTML 5 為<script>標(biāo)簽定義了一個新的擴展屬性:async。它的作用和 defer 一樣,能夠異步地加載和執(zhí)行腳本,不因為加載腳本而阻塞頁面的加載。但是有一點需要注意,在有 async 的情況下,JavaScript 腳本一旦下載好了就會執(zhí)行,所以很有可能不是按照原本的順序來執(zhí)行的。如果 JavaScript 腳本前后有依賴性,使用 async 就很有可能出現(xiàn)錯誤。

          3.2動態(tài)腳本元素

          文檔對象模型(DOM)允許您使用 JavaScript 動態(tài)創(chuàng)建 HTML 的幾乎全部文檔內(nèi)容。<script>元素與頁面其他元素一樣,可以非常容易地通過標(biāo)準(zhǔn) DOM 函數(shù)創(chuàng)建:

          清單 6 通過標(biāo)準(zhǔn) DOM 函數(shù)創(chuàng)建<script>元素

          新的<script>元素加載 script1.js 源文件。此文件當(dāng)元素添加到頁面之后立刻開始下載。此技術(shù)的重點在于:無論在何處啟動下載,文件的下載和運行都不會阻塞其他頁面處理過程。您甚至可以將這些代碼放在<head>部分而不會對其余部分的頁面代碼造成影響(除了用于下載文件的 HTTP 連接)。

          當(dāng)文件使用動態(tài)腳本節(jié)點下載時,返回的代碼通常立即執(zhí)行(除了 Firefox 和 Opera,他們將等待此前的所有動態(tài)腳本節(jié)點執(zhí)行完畢)。當(dāng)腳本是"自運行"類型時,這一機制運行正常,但是如果腳本只包含供頁面其他腳本調(diào)用調(diào)用的接口,則會帶來問題。這種情況下,您需要跟蹤腳本下載完成并是否準(zhǔn)備妥善。可以使用動態(tài) <script> 節(jié)點發(fā)出事件得到相關(guān)信息。

          Firefox、Opera, Chorme 和 Safari 3+會在<script>節(jié)點接收完成之后發(fā)出一個 onload 事件。您可以監(jiān)聽這一事件,以得到腳本準(zhǔn)備好的通知:

          清單 7 通過監(jiān)聽 onload 事件加載 JavaScript 腳本

          Internet Explorer 支持另一種實現(xiàn)方式,它發(fā)出一個 readystatechange 事件。<script>元素有一個 readyState 屬性,它的值隨著下載外部文件的過程而改變。readyState 有五種取值:

          &middot; "uninitialized":默認(rèn)狀態(tài)

          &middot; "loading":下載開始

          &middot; "loaded":下載完成

          &middot; "interactive":下載完成但尚不可用

          &middot; "complete":所有數(shù)據(jù)已經(jīng)準(zhǔn)備好

          微軟文檔上說,在<script>元素的生命周期中,readyState 的這些取值不一定全部出現(xiàn),但并沒有指出哪些取值總會被用到。實踐中,我們最感興趣的是"loaded"和"complete"狀態(tài)。Internet Explorer 對這兩個 readyState 值所表示的最終狀態(tài)并不一致,有時<script>元素會得到"loader"卻從不出現(xiàn)"complete",但另外一些情況下出現(xiàn)"complete"而用不到"loaded"。最安全的辦法就是在 readystatechange 事件中檢查這兩種狀態(tài),并且當(dāng)其中一種狀態(tài)出現(xiàn)時,刪除 readystatechange 事件句柄(保證事件不會被處理兩次):

          清單 8 通過檢查 readyState 狀態(tài)加載 JavaScript 腳本

          大多數(shù)情況下,您希望調(diào)用一個函數(shù)就可以實現(xiàn) JavaScript 文件的動態(tài)加載。下面的函數(shù)封裝了標(biāo)準(zhǔn)實現(xiàn)和 IE 實現(xiàn)所需的功能:

          清單 9 通過函數(shù)進行封裝

          此函數(shù)接收兩個參數(shù):JavaScript 文件的 URL,和一個當(dāng) JavaScript 接收完成時觸發(fā)的回調(diào)函數(shù)。屬性檢查用于決定監(jiān)視哪種事件。最后一步,設(shè)置 src 屬性,并將<script>元素添加至頁面。此 loadScript() 函數(shù)使用方法如下:

          清單 10 loadScript()函數(shù)使用方法

          您可以在頁面中動態(tài)加載很多 JavaScript 文件,但要注意,瀏覽器不保證文件加載的順序。所有主流瀏覽器之中,只有 Firefox 和 Opera 保證腳本按照您指定的順序執(zhí)行。其他瀏覽器將按照服務(wù)器返回它們的次序下載并運行不同的代碼文件。您可以將下載操作串聯(lián)在一起以保證他們的次序,如下:

          清單 11 通過 loadScript()函數(shù)加載多個 JavaScript 腳本

          此代碼等待 script1.js 可用之后才開始加載 script2.js,等 script2.js 可用之后才開始加載 script3.js。雖然此方法可行,但如果要下載和執(zhí)行的文件很多,還是有些麻煩。如果多個文件的次序十分重要,更好的辦法是將這些文件按照正確的次序連接成一個文件。獨立文件可以一次性下載所有代碼(由于這是異步進行的,使用一個大文件并沒有什么損失)。

          動態(tài)腳本加載是非阻塞 JavaScript 下載中最常用的模式,因為它可以跨瀏覽器,而且簡單易用。

          3.3使用 XMLHttpRequest(XHR)對象

          此技術(shù)首先創(chuàng)建一個 XHR 對象,然后下載 JavaScript 文件,接著用一個動態(tài) <script> 元素將 JavaScript 代碼注入頁面。清單 12 是一個簡單的例子:

          清單 12 通過 XHR 對象加載 JavaScript 腳本

          此代碼向服務(wù)器發(fā)送一個獲取 script1.js 文件的 GET 請求。onreadystatechange 事件處理函數(shù)檢查 readyState 是不是 4,然后檢查 HTTP 狀態(tài)碼是不是有效(2XX 表示有效的回應(yīng),304 表示一個緩存響應(yīng))。如果收到了一個有效的響應(yīng),那么就創(chuàng)建一個新的<script>元素,將它的文本屬性設(shè)置為從服務(wù)器接收到的 responseText 字符串。這樣做實際上會創(chuàng)建一個帶有內(nèi)聯(lián)代碼的<script>元素。一旦新<script>元素被添加到文檔,代碼將被執(zhí)行,并準(zhǔn)備使用。

          這種方法的主要優(yōu)點是,您可以下載不立即執(zhí)行的 JavaScript 代碼。由于代碼返回在<script>標(biāo)簽之外(換句話說不受<script>標(biāo)簽約束),它下載后不會自動執(zhí)行,這使得您可以推遲執(zhí)行,直到一切都準(zhǔn)備好了。另一個優(yōu)點是,同樣的代碼在所有現(xiàn)代瀏覽器中都不會引發(fā)異常。

          此方法最主要的限制是:JavaScript 文件必須與頁面放置在同一個域內(nèi),不能從 CDN 下載(CDN 指"內(nèi)容投遞網(wǎng)絡(luò)(Content Delivery Network)",所以大型網(wǎng)頁通常不采用 XHR 腳本注入技術(shù)。

          4.總結(jié)

          一般而言,減少 JavaScript 對性能的影響有以下幾種方法:

          &middot; A.將所有的<script>標(biāo)簽放到頁面底部,也就是</body>閉合標(biāo)簽之前,這能確保在腳本執(zhí)行前頁面已經(jīng)完成了渲染。

          &middot; B.盡可能地合并腳本。頁面中的<script>標(biāo)簽越少,加載也就越快,響應(yīng)也越迅速。無論是外鏈腳本還是內(nèi)嵌腳本都是如此。

          &middot; C.采用無阻塞下載 JavaScript 腳本的方法:

          &middot; a-使用<script>標(biāo)簽的 defer 屬性(僅適用于 IE 和 Firefox 3.5 以上版本);

          &middot; b-使用動態(tài)創(chuàng)建的<script>元素來下載并執(zhí)行代碼;

          &middot; c-使用 XHR 對象下載 JavaScript 代碼并注入頁面中。

          通過以上策略,可以在很大程度上提高那些需要使用大量 JavaScript 的 Web 網(wǎng)站和應(yīng)用的實際性能。


          看完了,別忘了收藏、轉(zhuǎn)發(fā)、點個贊,更別忘了要關(guān)注本號!^_^

          SS加載確實有可能阻塞頁面加載,但這并非絕對,具體取決于CSS的加載方式、應(yīng)用位置以及瀏覽器的渲染機制。在了解CSS加載如何影響頁面加載之前,我們先要明白瀏覽器渲染頁面的基本流程。

          瀏覽器在加載網(wǎng)頁時,會按照從上到下的順序解析HTML文檔。當(dāng)瀏覽器遇到`<link>`標(biāo)簽引用外部CSS文件時,它會停止HTML的解析,轉(zhuǎn)而加載并應(yīng)用這個CSS文件。這個過程被稱為CSS阻塞。因此,如果這個CSS文件很大或者加載速度很慢,用戶可能會看到一個空白頁面,直到CSS文件完全加載并應(yīng)用。

          然而,有幾種方法可以避免或減輕CSS加載對頁面加載的阻塞:

          1. 異步加載CSS:通過將CSS文件的加載設(shè)置為異步,可以確保HTML解析不會被阻塞。這可以通過在`<link>`標(biāo)簽中添加`rel="async"`屬性來實現(xiàn)。這樣,瀏覽器會在后臺加載CSS文件,而不會停止HTML的解析。
          2. 內(nèi)聯(lián)CSS:將CSS代碼直接寫在HTML文件中,而不是通過外部文件引用,可以避免網(wǎng)絡(luò)請求造成的延遲。但是,這會增加HTML文件的大小,可能導(dǎo)致其他性能問題。
          3. 使用CSS-in-JS庫:一些庫,如Styled Components或Emotion,允許你在JavaScript中編寫CSS。這種方法可以動態(tài)生成樣式,但也可能增加JavaScript的復(fù)雜性。
          4. 分割CSS:將CSS文件分割成多個小文件,每個文件只包含一部分樣式。這樣,即使某個文件加載較慢,也不會阻塞整個頁面的渲染。
          5. 利用媒體查詢:通過媒體查詢,你可以根據(jù)設(shè)備的特性(如屏幕大小、分辨率等)加載不同的CSS文件。這樣,用戶只會下載并應(yīng)用他們真正需要的樣式。
          6. 預(yù)加載和預(yù)獲取:使用`<link rel="preload">`和`<link rel="prefetch">`可以告訴瀏覽器提前加載CSS文件。雖然這并不能阻止CSS阻塞,但它可以確保文件在需要時立即可用。

          此外,值得注意的是,現(xiàn)代瀏覽器通常具有一些優(yōu)化機制,如并行下載、緩存等,這些都可以幫助減少CSS加載對頁面加載的影響。

          總的來說,CSS加載確實有可能阻塞頁面加載,但通過一些優(yōu)化策略和技術(shù),我們可以減輕或避免這種阻塞。選擇哪種策略取決于你的具體需求和約束。


          主站蜘蛛池模板: 精品人体无码一区二区三区| 无码精品人妻一区二区三区漫画| 在线播放一区二区| 精品人妻少妇一区二区| 欧亚精品一区三区免费| 日本一区二区在线不卡| 一区二区三区在线免费观看视频| 国模精品视频一区二区三区| 四虎成人精品一区二区免费网站| 蜜桃视频一区二区三区| 中文字幕精品无码一区二区三区 | 在线成人一区二区| 成人区人妻精品一区二区不卡| 日本精品一区二区三区四区| 视频一区二区三区免费观看| 中文字幕日韩丝袜一区| 视频一区二区在线播放| 精品人无码一区二区三区| 视频在线观看一区二区| 亚洲毛片不卡av在线播放一区| 无码人妻精品一区二区蜜桃网站| 麻豆AV无码精品一区二区| 国产精品免费综合一区视频| 精品不卡一区二区| 国产一区二区三区不卡观| 国产精品亚洲综合一区在线观看| 亚洲熟妇av一区| 国产精品va无码一区二区| 视频一区在线播放| 亚洲狠狠狠一区二区三区| 国产成人综合精品一区| 国产亚洲福利精品一区二区| 性色AV一区二区三区天美传媒| 国产成人久久精品麻豆一区| 综合无码一区二区三区| 精品无码日韩一区二区三区不卡 | 天天爽夜夜爽人人爽一区二区| 国产伦精品一区二区三区在线观看 | 亚洲精品一区二区三区四区乱码| 久久精品国产一区| 精品熟人妻一区二区三区四区不卡 |