作者:?緝熙Soyaine
簡介:JavaScript30 是 Wes Bos 推出的一個(gè) 30 天挑戰(zhàn)。項(xiàng)目免費(fèi)提供了 30 個(gè)視頻教程毛雇、30 個(gè)挑戰(zhàn)的起始文檔和 30 個(gè)挑戰(zhàn)解決方案源代碼盅视。目的是幫助人們用純 JavaScript 來寫東西椭赋,不借助框架和庫,也不使用編譯器和引用。現(xiàn)在你看到的是這系列指南的第 6 篇运提。完整指南在 GitHub峭竣,喜歡請 Star 哦?(?*)
實(shí)現(xiàn)效果
![仿即時(shí)搜索詩句效果](https://cl.ly/0b360y270s0f/Screen%20recording%202016-12-31%20at%2010.05.23%20PM.gif)
在輸入框中輸入一個(gè)詞,迅速匹配,展示含有這個(gè)詞的詩句中剩,詩句的來源 json 數(shù)據(jù)是加載頁面時(shí)從網(wǎng)絡(luò)中異步獲得忌穿。(原課程中選的內(nèi)容是英文城市名,我將其換成了唐詩结啼,地址可在我的頁面中獲嚷咏!)在線效果請查看。
初始文檔中提供了 HTML 和 CSS郊愧,我們需要補(bǔ)全 JS 代碼朴译。這個(gè)挑戰(zhàn)是 Ajax 的預(yù)熱練習(xí),在異步方面用到了一些目前還未被完全支持的新特性属铁,但很好用眠寿。
涉及特性
- Promise
fetch()
then()
json()
- Array
filter()
map()
push()
join()
- Spread syntax 擴(kuò)展語句
- RegExp
match()
replace()
過程指南
- 聲明一個(gè)空數(shù)組,用于存放解析 json 后的數(shù)據(jù)
- 運(yùn)用
fetch()
發(fā)送 HTTP 請求- 獲取返回的 Promise 對象
- 解析 JSON 數(shù)據(jù)
- 存入數(shù)組
- 獲取兩個(gè)主要 HTML 元素(
<input>
焦蘑,<ul>
)盯拱,給<input>
添加事件監(jiān)聽(change
,keyup
) - 編寫匹配輸入的函數(shù)
- 運(yùn)用
filter()
過濾數(shù)組數(shù)據(jù) - 創(chuàng)建正則表達(dá)式,構(gòu)造過濾條件
- 運(yùn)用
- 編寫展示匹配結(jié)果的函數(shù)
- 獲取匹配數(shù)據(jù)
- 替換關(guān)鍵詞放入高亮的標(biāo)簽
- 構(gòu)造 HTML 標(biāo)簽數(shù)據(jù)
- 將匹配值的 HTML 標(biāo)簽放入
<ul>
中
相關(guān)知識
Fetch API
Fetch API 這個(gè)新特性例嘱,是 XMLHttpRequest 獲取資源新的替代方案狡逢,目前還是一個(gè)實(shí)驗(yàn)中的功能,截至到 2017.01.01 在 MDN 顯示的支持情況是:Chrome 42.0拼卵、Firefox (Gecko) 39奢浑、Opera 29、Chrome for Android 42.0腋腮、Android Webview雀彼。如何使用可以看這篇文章。
fetch()
Fetch API 提供一個(gè)全局的方法 fetch()
即寡,這個(gè)方法(至少)需要接受 資源的路徑
作為參數(shù)徊哑,返回值是一個(gè) Promise 對象。若請求成功嘿悬,這個(gè)對象包含了(對應(yīng) Request 的)Response实柠,但這只是一個(gè) HTTP 響應(yīng)。
語法如下:
fetch(input, init).then(function(response) { ... });
MDN 中有個(gè)發(fā)送基本的 fetch 請求的示例如下:
var myImage = document.querySelector('img');
fetch('flowers.jpg')
.then(function(response) {
return response.blob();
})
.then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
});
用 ES6 的語法來寫就是這樣:
const myImage = document.querySelector('img');
fetch('flowers.jpg')
.then(response => response.blob())
.then(myBlob => {
const objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
});
這個(gè)示例中使用了 blob()
方法來獲取圖片的內(nèi)容善涨,這是 Body 類定義的一個(gè)方法窒盐,除此之外還有可以獲取其他內(nèi)容的方法,可以在這里看钢拧,也可以在 Console 面板中查看:
![Body 類的方法](https://cl.ly/143N2R1b3T1o/Image%202017-01-03%20at%209.15.37%20AM.png)
在這個(gè)挑戰(zhàn)中蟹漓,我們主要是利用 .json()
,以使用 JSON 對象來讀取 Response 流中的數(shù)據(jù)源内,讀取之后葡粒,Body 的 body.Uesd 屬性值會變?yōu)橐炎x。另外較為常用的方法還有:blob()
、text()
嗽交、arrayBuffer()
卿嘲、formData()
。
ES6 中的數(shù)組擴(kuò)展語法
利用擴(kuò)展運(yùn)算符可以替代 ES5 中的 push
方法添加一個(gè)數(shù)組到另一個(gè)數(shù)組末尾夫壁,兩種語法的寫法如下:
// 將arr2中的所有元素添加到arr1中
// ES5
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2);
// ES6
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2);
此挑戰(zhàn)中如何異步獲取數(shù)據(jù)并解析
這一部分用到的語句很簡單拾枣,但都用了 ES6 的語法,所以不熟悉 ES6 的話需要時(shí)間適應(yīng)一下盒让。
const endpoint = 'https://raw.githubusercontent.com/soyaine/FE-Practice/f438d3bdf099461f88322b1b1f20c9d58f66f1ec/TangPoetryCut.json';
const poetrys = [];
fetch(endpoint)
.then(blob => blob.json())
.then(data => poetrys.push(...data));
如果把每條語句分解開來運(yùn)行梅肤,得到的返回結(jié)果可以看下面的截圖。
![fetch(url).then()](https://cl.ly/3P3F1F2y1510/Image%202017-01-01%20at%206.58.45%20PM.png)
正則表達(dá)式
獲取到了數(shù)據(jù)之后邑茄,如何匹配輸入值呢姨蝴?就要利用正則表達(dá)式了。正則表達(dá)式的 match()
可以執(zhí)行一個(gè)匹配操作肺缕,我們再結(jié)合 Array.filter()
便能篩出整個(gè)數(shù)組中左医,滿足條件的項(xiàng),再經(jīng)過字符串處理即可輸出到頁面同木。
這篇我寫了很久也寫不滿意炒辉,如果你能讀到這里,說明你對實(shí)現(xiàn)的效果有興趣泉手,如果你覺得有什么地方我寫得不清楚,或者我遺漏了什么偶器,請告訴我斩萌。我一直在思考和調(diào)整,用什么樣的方式去寫會比較容易看懂屏轰,萬分期待和感恩能有讀者反饋 soyaine1@gmail颊郎。
創(chuàng)建時(shí)間:2016-12-31
最后更新:2017-01-03