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