我們的日常前端開發工作中,經常會用到javascript技術,那么javascript獲取元素的方法有哪些,大家都知道嗎?目前獲取元素屬性的方法中最常見的有8個,包括innerHTML、outerHTML、innerText 、outerText、value、text()、html(),val(),讓我們分別了解下應用方法吧。
1、innerHTML 屬性
在讀模式下,innerHTML屬性返回與調用元素的所有子節點(包括元素、注釋和文本節點)對應的 HTML 標記。在寫模式下,innerHTML 會根據指定的值創建新的 DOM 樹,然后用這個 DOM 樹完全替換調用元素原先的所有子節點。下面是一個例子:
對于上面的元素來說,它的 innerHTML 屬性會返回如下字符串。
2、outerHTML 屬性
在讀模式下,outerHTML 返回調用它的元素及所有子節點的 HTML 標簽。在寫模式下,outerHTML 會根據指定的 HTML 字符串創建新的 DOM 子樹完全替換調用元素。下面是一個例子。
如果在元素上調用 outerHTML,會返回與上面相同的代碼,包括本身。使用 outerHTML 屬性以下面這種方式設置值:
這行代碼完成的操作與下面這些 DOM 腳本代碼一樣:
結果,就是新創建的元素會取代 DOM 樹中的元素。
replaceChild() 方法用新節點替換某個子節點。
語法:
3、innerText 屬性
通過 innerText 屬性可以操作元素中包含的所有文本內容,包括子文檔樹中的文本。在通過 innerText 讀取值時,它會按照由淺入深的順序,將子文檔樹中的所有文本拼接起來。在通過 innerText 寫入值時,結果會刪除元素的所有子節點,插入包含相應文本值的文本節點。下面是一個例子:
對于這個例子中的元素而言,其中 innerText 屬性會返回下列字符串:
使用 innerText 屬性設置這個元素內容,則只需一行代碼:
執行這行代碼后,頁面的 HTML 代碼就會變成如下所示:
設置 innerText 屬性移除了先前存在的所有子節點,完全改變了 DOM 樹。設置 innerText 永遠只會生成當前節點的一個子文本節點,而為了確保只生成一個字文本節點,就必須要對文本進行 HTML 編碼。利用這一點,可以通過 innerText 屬性過濾掉 HTML 標簽。方法是將 innerText 設置等于 innerText,這樣就可以去掉所有 HTML 標簽,比如:
執行這行代碼后,就用原來的文本內容替換了容器元素中的所有內容(包括子節點,因而也就去掉了 HTML 標簽)。舉個栗子:
輸出:
4、outerText 屬性
除了作用范圍擴大到了包含 調用它的節點之外,outerText 與innerText 基本上沒有多大區別。在讀取文本值時,outerText 與 innerText 的結果完全一樣。但在寫模式下,outerText 就完全不同了:outerText 不只是替換調用它的元素的子節點,而是會替換整個元素(包括子節點)。比如:
這行代碼實際上相當于如下兩行代碼:
本質上,新的文本節點會完全取代調用 outerText 的元素。此后,該元素就從文檔中被刪除,無法訪問。
5、value 屬性
屬性可設置或返回密碼域的默認值。獲取文本框的值。
6、text()
設置或者獲取所選元素的文本內容
1)無參text():取得所有匹配元素的內容。結果是由所有匹配元素包含的文本內容組合起來的文本。返回的是一個String。
2)有參text(val):設置所有匹配元素的文本內容,與 html() 類似, 但將編碼 HTML (將 “<” 和 “>” 替換成相應的HTML實體).返回一個jquery對象。
7、html():
設置或者獲取所選元素的內容(包括html標記)
1)無參html():取得第一個匹配元素的html內容。這個函數不能用于XML文檔。但可以用于XHTML文檔,返回的是一個String。
2)有參html(val):設置每一個匹配元素的html內容。這個函數不能用于XML文檔。但可以用于XHTML文檔。返回一個jquery對象。
8、val()方法
主要用于獲取表單元素的值如input, select 和 textarea。當在一個空集合上調用,它返回undefined;1)無參 val():獲取匹配的元素集合中第一個元素的當前值。例子:HTML代碼:
控制臺輸出:
2)有參val(val):設置每一個匹配元素的值。返回一個jquery對象。
大家對以上的8個javascript獲取元素的方法是否有了一些了解呢?根據獲取元素方法的不同,所應用的場景也不相同。想要熟練地使用這8種方法,就需要了解它們各個特征。更多關于前端培訓的問題,歡迎咨詢云和數據官網。云和數據擁有多年IT培訓服務經驗,采用全程面授高品質、高體驗培養模式,擁有國內一體化教學管理及學員服務,助力更多學員實現高薪夢
一篇文章我給大家說明了如何從零開始搭建一個node的服務端框架,我們用到了Egg框架。Egg框架我不再過多介紹,如果有小伙伴想了解,可以回去看我以前寫的文章,會有相關的介紹。這次我將在上次搭建的框架上進行延伸,講一下如果用Egg框架連接數據庫,并且實現對數據的增刪查改。接下來我們直接進入主題。
我本次選用的數據庫是MySQL。所以我們安裝Egg官方的數據庫插件即可,首先我們安裝插件 egg-mysql 。我們在項目根目錄打開命令提示符,輸入命令行:npm i --save egg-mysql 。回車等待插件下載安裝完成。
npm i --save egg-mysql
命令行下載安裝插件完成后,我們下一步的工作就是在項目中開啟并配置egg-mysql插件。具體操作如下:
首先我們要在項目中開啟數據庫。找到項目中的/config/plugin.js文件我們需要在里面添加幾行代碼,如下所示。
//開啟數據庫插件
mysql : {
enable: true,
package: 'egg-mysql',
}
然后我們還要在 config/config.default.js 中配置各個環境的數據庫連接信息。具體配置如下。
//添加數據庫連接信息
config.mysql = {
// 單數據庫信息配置
client: {
// host
host: 'localhost',
// 端口號
port: '3306',
// 用戶名
user: 'root',
// 密碼
password: '123456',
// 數據庫名
database: 'testdb',
},
// 是否加載到 app 上,默認開啟
app: true,
// 是否加載到 agent 上,默認關閉
agent: false,
};
到此步驟我們的數據庫插件已經安裝完成并且配置好了。那我們怎么實現數據的增刪查改呢?大家請繼續往下看。
首先我們看一下怎么新增數據。我們在mysql的testdb實例中新建一個user空表。如下圖所示。
我們的egg框架也遵循MVC的架構所以我們一般會在service層里面寫我們邏輯處理的代碼,而controller層則是獲取前端數據,回傳數據的控制層。所以我們操作數據庫的代碼是寫在service文件夾里面的。
我們在app/service文件夾里面新建一個user.js文件。在里面寫個新增用戶的方法,該方法就是把數據存到數據庫中。具體代碼如下。
const Service = require('egg').Service;
class UserService extends Service {
//新增用戶data是有controller層傳遞過來的數據記錄。
async addUser(data) {
const {ctx, app} = this;
let result = {};
try {
data.id = 0;//定義id=0,因為數據庫已經設置id為主鍵,并且自增。所以只需要賦值0即可。
// 在 user 表中,插入前端提交上來的數據記錄
const info = await app.mysql.insert('user', data);
//插入成功后。
if(info.affectedRows === 1){
//給前端返回一個Json的對象
result = {
state: 0, //自定義的狀態碼
msg: "添加成功", //返回的消息
data: info.insertId, //新增的記錄的id
}
}
} catch (err) {
//插入數據失敗的返回結果
result = {
state: 1,
msg: err,
data: null,
}
}
return result
}
};
module.exports = UserService;
然后我們在app/controller文件夾里新建一個user.js文件。在這里我們需要獲取前端提交上來的數據,并且將數據處理的結果返回給前端。具體代碼如下。
'use strict';
const Controller = require('egg').Controller;
/**
* @Controller 用戶管理
*/
class UserController extends Controller {
/**
* @summary 新增用戶
* @router post /user/add
* @request body userAddRequest
* @response 200
*/
async addUser() {
const { ctx } = this;
//通過ctx.request.body的方式,可以獲取到前端post方式提交上來的數據
const data = ctx.request.body;
//調用service層的addUser方法。并且返回相應的結果
const userInfo = await ctx.service.user.addUser(data);
//向前端接口響應數據。
ctx.body = userInfo;
}
}
module.exports = UserController;
最后我們定義一個路由,讓前端請求訪問此路由。框架會監聽路由是否被訪問,如果被訪問了則會調用我們定義在controller層的新增用戶的方法。我們在app/router.js文件中添加如下代碼,即可完成路由的定義。
//新增用戶路由
router.post('/user/add', controller.user.addUser);
完成這步驟后,我們一個新增用戶的功能就已經完成了。接下里我們就測試一下它的實際效果。我們運行命令:npm run dev。啟動項目,然后打開網頁http://127.0.0.1:7001,可以直接在swagger-ui.html頁面中進行測試。結果如下圖所示。
經過測試,數據已經添加完成。所以數據庫連接也是正常的。
本次分享暫時先告一段落。請各位小伙伴抬起你們發財的小手,點個贊唄。下次我將會進行和大家分享對數據查改刪的方法。關注我!!!更多精彩分享不迷路。
載說明:原創不易,未經授權,謝絕任何形式的轉載
在當今充滿活力的網絡開發領域中,實現強大的搜索功能是一個關鍵特性,可以極大地增強用戶體驗,并使瀏覽大型數據集變得輕松自如。如果您想要為您的網站或網絡應用程序添加實時搜索功能,那么您來對地方了。本篇全面的文章將探討使用JavaScript實現實時搜索功能的方方面面。
無論您是經驗豐富的開發人員還是剛開始編碼之旅的新手,本文旨在為您提供一般編碼知識和工具,以便將實時搜索功能融入到您的項目中。通過本指南的學習,您將對相關概念和技術有扎實的理解,從而能夠創建響應式和交互式的搜索功能,實現用戶輸入時動態更新的效果。
為了有效地跟隨本指南,建議您對HTML、CSS和JavaScript的基本知識有扎實的理解。熟悉DOM操作和事件處理將有助于我們深入了解實現細節。然而,即使您對JavaScript或Web開發相對較新,本指南的結構也旨在提供清晰的解釋和逐步的說明,使其適用于不同技能水平的學習者。
現在,為了更好地理解這個功能的重要性和使用方法,我們將創建一個非常基本的項目作為示例;更具體地說,一個如下所示的電影應用程序:
您可以在這里查看實時實施情況。
https://search-movies-live.netlify.app/
在這個項目中,我們將利用實時搜索功能來搜索電影數據庫中的電影列表。我知道你迫不及待地想要開始了,我們馬上就會開始。但首先,讓我們更多地了解一下實時搜索功能及其重要性。
在當今數字化的環境中,實時搜索功能變得至關重要,滿足了高效信息檢索的需求,提升了整體用戶體驗。通過在用戶輸入時實時更新搜索結果,實時搜索提供即時反饋,便于快速獲取相關信息。這種動態交互式的搜索功能帶來了許多好處,使用戶和網站所有者受益。
既然我們已經完全了解了實時搜索功能以及它的重要性,那么讓我們深入探討一下如何在您自己的項目中實現這個功能。
首先,讓我們建立項目的結構。對于這個項目,我們只需要三個文件,即HTML、CSS和JavaScript文件。
現在讓我們開始設置項目的HTML結構:在HTML文件中,我們首先需要包含我們的標準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>
現在在 body 標簽中,我們包含了 header 和 main 語義標簽。在 header 標簽內,我們設置了項目的標題部分,這里只包括應用程序的名稱和一個視頻圖標。
<header>
<ion-icon name="videocam"></ion-icon>
<h1>Search Movies</h1>
</header>
在我們繼續講解 main 標簽之前,在 body 標簽的末尾,讓我們包含所需的 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>
您可以在Ionicons網站上找到這些圖標。
https://ionic.io/ionicons
現在,在 main 標簽內,我們將包含我們的第一個 div 標簽,這將是我們的搜索欄容器,在其中,我們放置我們的搜索輸入標簽和一個搜索圖標:
<div id="search-container">
<ion-icon name="search-outline"></ion-icon>
<input type="search" id="search-bar" placeholder="Search movies..." />
</div>
然后,我們將在這個“div”下面創建另一個 div 標簽。這將包含所有電影數據的結果:
<div id="results-container"></div>
我們暫時將其留空,因為其內容將在JavaScript部分生成。
最后,在 main 標簽中,我們將包含一個 p 標簽。這個標簽只是為了在稍后向用戶顯示錯誤或空消息的響應。
<p id="movie-unavailable-txt"></p>
這就是HTML文件的全部內容,整體代碼應該是這樣的:
<!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>
既然我們已經完成了項目的HTML結構的實現,那么讓我們給頁面添加一些樣式。
在這個部分,我們將為頁面的各個部分添加基本的樣式。所以讓我們開始吧。首先,讓我們為頁面的整體部分添加一些常規樣式:
html{
scroll-behavior: smooth;
background-color: #111;
color: whitesmoke;
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
現在讓我們為頭部部分及其內容添加一些樣式:
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%;
}
接下來,我們開始對搜索容器及其內容進行樣式設置:
#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;
}
之后,我們繼續設計將來從電影數據庫中獲取的所有電影的 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 設置為 none ,因為我們暫時不希望它可見
#movie-unavailable-txt{
text-align: center;
letter-spacing: 2px;
display: none;
margin-top: 15%;
text-shadow: 3px 3px 5px #fd1d6b;
}
接下來,我們將為一些尚未聲明但將通過JavaScript創建的元素添加一些樣式。這是電影卡片,將顯示電影的詳細信息,包括電影圖片和標題:
.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;
}
既然我們已經完成了頁面的樣式,那么讓我們繼續進行最有趣和最重要的部分,即Javascript的實現。
在本節中,我們將調用我們選擇的電影數據庫API來填充我們的頁面,展示各種電影。在這種情況下,我將使用RapidAPI Hub中的IMDb Top 100 Movies免費電影API。在API頁面中,我們選擇要使用的特定數據,然后復制頁面右側提供的javascript(fetch)代碼,如下所示:
https://rapidapi.com/rapihub-rapihub-default/api/imdb-top-100-movies
首先,在您使用API之前,請先訂閱它(無需信用卡),以便為您生成一個API密鑰。您可以在API的定價頁面上進行訂閱。
繼續,我們進入我們的空的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",
},
};
try {
const response = await fetch(url, options);
const result = await response.text();
console.log(result);
} catch (error) {
console.error(error);
}
既然我們已經將電影數據庫的API引入到我們的項目中,我們可以使用它的數據了。接下來,我們將聲明一些我們需要的變量,并將它們放在我們復制的代碼中 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;
我們正在接近剛剛創建的這些變量的目的,堅持住。
接下來,我們對復制的代碼中的 try 塊進行一些更改,因為我們希望將其與我們的項目完全集成。所以首先,我們需要創建一個異步函數:
const fetchMovies = async () => {
// try catch block goes in here.
};
在這個函數內部,我們將放置從我們復制的代碼中的整個 try catch 塊,以便我們可以進行異步API調用。
在 try 塊內,我們將刪除 console.log(result) 行,并將 result 變量更改為先前聲明的 movieList 變量,并將同一行中的 response.text() 更改為 response.json() 。這樣,我們從API調用中接收到的數據將以 JSON 格式呈現,這是我們所需的。因此,該行現在應該是這樣的
movieList = await response.json();
現在我們已經成功從API中獲取了電影并返回了我們的數據集,我們需要將這些數據填充到我們的頁面中。為此,我們將調用 renderMovies() 函數,并將參數設置為從API調用中獲取的數據。不用擔心,我們很快就會創建這個函數:
renderMovies(movieList);
現在讓我們創建 renderMovies 函數,這個函數剛剛在 fetchMovies() 函數中調用過,這個函數將用于創建動態電影卡片模板,我們之前在CSS文件中設置了樣式,模板中的每個元素的內容都將設置為從API獲取的數據,這樣我們就可以使用相同的模板渲染不同的電影。然后,我們將把電影卡片放在 resultsContainer 元素中。每次調用函數時,我們需要清除 resultsContainer ,并將 moviesUnavailableTxt 設置為 display="none" ,因為我們希望在渲染電影到頁面時文本不可見,同時清除 moviesReturnedOnSearch 數組,然后將從搜索輸入字段返回的新數據設置到其中。
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
});
};
現在我們已經將所有電影數據加載到我們的頁面上,接下來是真正有趣的部分,我們要實現實時搜索功能,所以,不浪費時間,讓我們開始吧。
為了捕獲用戶輸入,我們將使用 input 事件監聽器,并將其鏈接到 searchBar 元素。我們使用這個特定的事件監聽器,因為它可以捕獲搜索框內的每一個活動,包括輸入、清除和粘貼,這正是我們想要的。所以讓我們繼續創建它:
searchBar.addEventListener("input", (event) => {
// live functionality code
});
好的,現在我們已經將事件監聽器鏈接到搜索欄,以便監聽用戶的任何輸入。在第二個參數中,我們添加了事件處理程序,這是每當搜索欄有輸入時將被調用的函數。現在,在該函數內部,我們將編寫處理實時搜索的代碼。
在搜索功能中,我們需要做的第一件事是編輯從用戶那里獲取到的輸入值,并將其轉換為全小寫,同時去除任何不必要的空格:
searchValue = event.target.value.trim().toLowerCase();
在那之后,我們繼續根據用戶的搜索輸入,通過檢查用戶輸入的電影標題是否包含在 movieList 數據中的任何電影標題中,并將電影標題設置為小寫以與用戶輸入匹配,來在頁面上按標題篩選電影
const filteredMovies = movieList.filter( (movie) => movie.title.toLowerCase().includes(searchValue) );
接下來,我們將通過再次調用 renderMovies() 函數,并將參數設置為 filtered Movies 變量的值,來顯示與用戶在搜索欄中輸入的字符匹配的電影標題的實時搜索結果。
renderMovies(filteredMovies);
通過調用此函數,它僅將與搜索欄中鍵入的字符匹配的電影渲染到頁面上,使用函數中提供的電影卡片模板,同時將每個匹配的電影添加到 moviesReturnedOnSearch 數組中,以便我們可以跟蹤每個字符輸入的匹配搜索值的電影數量。在處理空響應錯誤時,這將非常有用,現在我們將進入這個部分。
在任何應用程序中,有效處理空或錯誤的響應至關重要。在這種情況下,這些情景可能發生在搜索查詢沒有結果或API請求存在問題時。
處理錯誤或空響應時,向用戶提供清晰的反饋是至關重要的。話雖如此,由于這是一個相對簡單的應用程序,我們不必過多擔心錯誤,因為我們只需要處理由API引起的錯誤。例如,API服務可能暫時不可用,或者應用程序可能剛剛超過了請求限制。為了處理這個錯誤,我們只需要將 movieUnavailableTxt 元素的 display 設置為 block ,并將 innerHTML 設置為向用戶顯示錯誤消息,并將其放置在 fetchMovies() 函數的 catch 塊中。因此,現在 catch 塊的代碼如下所示:
catch (error) {
movieUnavailableTxt.innerHTML = 'An error occurred while fetching movies. <br /> Please try again later.';
movieUnavailableTxt.style.display = "block";
console.error(error);
}
現在我們已經處理完錯誤響應,接下來我們要處理空響應。如果用戶搜索的電影與頁面上的任何電影都不匹配,我們需要向用戶提示所搜索的電影不可用。為了做到這一點,首先我們需要檢查之前聲明的 moviesReturnedOnSearch 數組的內容,如果數組的長度小于或等于0,我們將設置 movieUnavailableTxt 元素的 display 為 block ,并將 innerHTML 設置為空響應消息,如下所示:
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實現實時搜索功能時,提高性能的一種有效技術是緩存。緩存涉及存儲先前獲取的搜索結果,并在再次請求相同的搜索查詢時重復使用它們。這可以顯著減少API調用的次數,有助于防止超過API的請求限制,并改善搜索功能的響應速度以及網站的加載時間。
要在我們的項目中實現緩存,首先,我們需要確定哪些項目需要被緩存,而在這種情況下,那將是 movieList 變量的值,它是我們從 fetch API請求中得到的 JSON 格式的數據。通過緩存這個項目,我們將能夠在頁面重新加載時使用API的數據,而無需進行額外的 fetch 請求。但是對于這個項目,我們將為我們的緩存數據設置一個過期時間,為6小時,這意味著頁面每6小時只會進行一次API請求,而不是在每次頁面重新加載時都進行請求。這樣做是為了保持頁面的數據新鮮和最新,同時將API請求保持在最低限度。
回到我們的代碼中,現在我們需要將數據存儲在瀏覽器的本地存儲中,但為了做到這一點,我們需要首先將其轉換為一個 string ,并設置一個鍵名,用于在本地存儲中標識數據。讓我們將其設置為 movieData ,如下所示:
localStorage.setItem("moviedata", JSON.stringify(movieList));
接下來我們需要將當前日期和時間存儲在本地存儲中:
localStorage.setItem("cacheTimestamp", Date.now());
這將當前日期和時間以毫秒為單位存儲,鍵名為 cacheTimeStamp 。
我們將把這兩行代碼放在 try 塊的 fetchMovies() 函數中,就在 movieList 變量的下方。
接下來,在 fetchMovies() 函數之外,緊接著 renderMovies() 函數的下方,我們將把緩存數據的過期時間設置為6小時(以毫秒為單位)
const expirationDuration = 21600000; // 6 hours in milliseconds
之后,我們需要取回之前在本地存儲中設置的 cacheTimestamp :
const cacheTimestamp = localStorage.getItem("cacheTimestamp");
現在,我們將檢查緩存數據是否已過期或不可用,這意味著它尚未被存儲。如果是這種情況,我們將通過調用 fetch 函數向API發出新的請求。另一方面,如果緩存數據存在且尚未過期,我們將使用它來渲染頁面上的電影,而不是再次發出新的 fetch 請求。我們通過檢索緩存的電影數據并將其解析回 JSON 格式來使用,然后將參數設置為從緩存中獲取的數據,調用 render 函數來實現這一點。
// 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 為假,表示沒有存儲現有緩存時間戳。 Date.now() - parseInt(cacheTimestamp) 計算當前時間戳與解析的 cacheTimestamp 的整數值之間的時間差。簡單來說,這就是說:“當前時間的值減去我們之前存儲在緩存中的時間的值,是否大于我們設置的過期時間?如果是,就從API中重新獲取電影數據;如果不是,就使用緩存的數據。”
就是這樣,這就是我們如何將數據緩存起來以便重復使用,而不是在每次用戶輸入或每次頁面重新加載時發起請求。正如你所看到的,這將極大地優化應用程序的性能,因為它可以防止由于網絡慢而導致的電影渲染緩慢。
我們已經完成了我們的小電影應用程序中展示實時搜索功能的所有特性的實現。以下是該應用程序的整體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
}
});
在本指南中,我們探討了使用API在JavaScript中實現實時搜索功能的方法。按照所述步驟,您可以創建一個動態搜索體驗,當用戶在搜索欄中輸入時,可以提供實時結果。
通過在您的網站上實現實時搜索功能,您可以增強用戶參與度,提高您的網站或應用程序的可用性。用戶將欣賞能夠快速方便地找到相關信息,而無需重新加載頁面。
通過這個指南所獲得的知識,您已經具備了在JavaScript中有效實現實時搜索功能的能力。擁抱動態搜索的力量,創造一個無縫的用戶體驗,給人留下深刻的印象。
由于文章內容篇幅有限,今天的內容就分享到這里,文章結尾,我想提醒您,文章的創作不易,如果您喜歡我的分享,請別忘了點贊和轉發,讓更多有需要的人看到。同時,如果您想獲取更多前端技術的知識,歡迎關注我,您的支持將是我分享最大的動力。我會持續輸出更多內容,敬請期待。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。