这次的章节,对于正规表达式不熟悉的我,是个非常难理解的,花了大概半天才理解清楚,程式码全部的意思,也希望如果有地方写得不好,请见谅,或是大大能够补充,谢谢!
这次的功能是很常见的搜寻功能,给予关键字,并会在搜寻栏下面呈现符合条件的资料。
fetch vs XMLHttpRequest
首先我们要获取资料,排除axios之外,获取资料又有分为两种方式
一种为fetch,一种为XTMLHttp,两者最大差异在于一个用callback,一个用promise
fetch虽操作较XML简单,但目前不支持进度条,超时,错误不会被拒绝。
XMLHttpRequest虽较複杂,但支持许多功能
XMLHttpRequest写法:
function requestHandler() { if (this.readyState !== 4) return; if (this.status === 200) { console.log(JSON.parse(this.response)); } else { console.log('HTTP error'); } } let req = new XMLHttpRequest(); req.addEventListener('load', requestHandler); // endpoint为要获取的资料 req.open('GET', endpoint); req.send();
fetch写法:
// endpoint为要获取的资料 fetch(endpoint) .then(item => item.json()) .then(data => console.log(data)) .catch(error => console.log(error));
fetch获取资料又有两种方式:一是直接赋值,二是解构后放进去。
let为变数宣告
,除非我们所设的值是可变的用let。const为常数宣告
,在设置常数,阵列,物件,函数等类型都用const。
直接赋值
// 直接设置空值,赋值并获取资料 // 由于cosnt一定要有值,所以不可用const宣告 let cities = null; fetch(endpoint) // 将资料解析(json()) .then(item => item.json()) .then(data => cities = data) // 已成功获取资料 .then(cities => console.log(cities));
解构赋值
// 一种设置空阵列,并利用解构一个个放进去 const citiess = []; fetch(endpoint) .then(item => item.json()) .then(data => citiess.push(...data));
获取完资料后,我们要获取输入的关键字,也就是获取我们的input并增加监听事件,当关键字改变时触发,input、或keyup事件也可不用change事件
,因为在< input >,< select >,< textarea >内的值改变时且不是 focus 状态时触发
,也就是要当鼠标不在栏位,才会触发,故不适合。
document.querySelector('.search').addEventListener('input', inputHandler);
而在触发后,呼叫一个函数,用来处理资料,如过滤资料、关键字的反黄,人口数的格式等。
首先,将我们的关键字以及全部资料传入至一个专门处理资料,但不影响原资料的Purefunction。
// 将我们所输入的值(第一个参数),及全部的资料(第二个参数),传入findMatches并进行过滤 const matchArray = findMatches(this.value, cities);
RegExp
正则表达式就是用于查找符合某些複杂规则的字符串的工具
,在 JavaScript 中,正规表达式也是物件。
常见的写法有两种:
一种为: 用RegExp常数,包含两个 / 字元之间的模式
const regex = /bc/gi;
一种为: 呼叫RegExp物件的建构子函数
const regex = new RegExp('los', 'gi');
正规表达之特殊字元:
正规表达模式由数个简易字元组成,例如 /abc/,或是由简易字元及特殊符号组合而成,每种组合都代表不同意思
。
\B:放在前面,代表前面要有东西(英文、数字、_),放在后面反之。
\b :放在前面,代表前面要没有东西,后面反之。
(?=xxx):要符合xxx。
\d:d是数字,这边是指所有数字0-9。
{}:代表字元出现次数。
+:代表+前面的字元可出现1次或多次。
(?!=xxx) : 不能符合xxx。
g : 会匹配全部
extra common
^ : 要符合在首位,ex:/^B/,Beach符合,DoBule不符合
$ : 要符合在末位,ex:/d$/,bad符合,dark不符合
. : 只要没有换行符号都符合,ex:/.a/,w a h符合,abc不符合
i : 不分大小写匹配
米字号 : 放在字后面,代表有0个对应字或多个字,ex:/ab*c/,abbbc符合,acb不符合
本实作程式码:
由后往前比较,g为匹配全部的资料,而最后一个不能为数字,且前面必须为三个数字,且可以为一组以上,而最前面要有东西结论就是最前面要有东西,且要符合每三个数字为一组,至少一组(三个数字)以上,且最后面不为数字才符合
。
function populationHandler(num) { return num.replace(/\B(?=(\d{3})+(?!\d))/g, ',');};
match():此方法会回传一含比对成功字串为元素的阵列,若无符合字元则回传null。
他会利用正规表达式来比对搜寻字串
。
string.match(regexp)
参数为regexp(正规表达式物件),如果不是,会被隐式的使用new RegExp(obj)转化成正规表达式物件。
purefunction
而下面这段代码,在const regex部分,创建一个正规表达式,第一个参数为我们所输入的关键字,
第二个参数g为比对全部资料,i为不分大小写,而在最后return部分,就是在比对资料,符合的话就返回。
// purefunction,也就是不会改变这个function以外的东西(如word,cities), // 经过这个function,word,cities不变,只是拿进来使用,处理完后,最后回传一个阵列。 function findMatches(word, cities) { return cities.filter(place => { // 利用正规表达式,去筛选符合条件的资料 const regex = new RegExp(word, 'gi'); // 只要其中一项(资料的城市或地区)符合,就回传以阵列型式且符合的资料 return place.city.match(regex) || place.state.match(regex) }); }
replace :此方法会寻找符合的字元,并将他们以新的字元去做替换。
注意replace如果第一个参数为正则,可以把全部都替换,如果单纯用replace,换完第一个就会停止
如
const a = '88cdefg88';const regex = new RegExp('88', 'gi');参数为正则,全部替换a.replace(regex,gg); // ggcdefgg参数为常数,替换一个就停止a.replace('88',gg); // ggcdef88
toLocaleString:将数值型别的资料,更改为不同的显示方式,预设为英文语系,故每三个数字一个逗号
此外,除了使用正规表达式来设置数字格式之外,我们还可利用toLocaleString来达到效果。
function populationHandler(num) { // 因为在json中资料(population)是以字串型式,所以为了使用toLocaleString, // 要将资料转为数值,故利用*1强制转型即可 return (num * 1).toLocaleString();};
join():join将字串以括号内的元素合成一个字串
不加上参数的话预设以,隔开,此处用空不加上join的话,每个Li中间都会有逗号隔开(因为阵列关係)。
如下图
function inputHandler() { // 将我们所输入的值(第一个参数),及全部的资料(第二个参数),传入findMatches并进行过滤 const matchArray = findMatches(this.value, cities); console.log(matchArray); // 会获取条件过滤后的资料 // 获取过滤完的资料后,以列表呈现在搜寻框下 const html = matchArray.map(place => { const regex = new RegExp(this.value, 'gi'); // 将地区及城市的关键字,以有颜色的字体去取代 const cityName = place.city.replace(regex, `<span class="hl">${this.value}</span>`); const stateName = place.state.replace(regex, `<span class="hl">${this.value}</span>`); // 最后回传符合条件的城市,地区,及处理好的对应人口 return ` <li> <span class="name">${cityName}, ${stateName}</span> <span class="population">${numberWithCommas(place.population)}</span> </li> `; // join将字串以括号内的元素合成一个字串,预设为,,此处用空 // 不加join的话每个Li中间都会有逗号隔开(因为阵列关係) }).join(''); console.log(html); document.querySelector('.suggestions').innerHTML = html; }
而我们再拿到过滤完的资料后,需要将资料呈现出来,因为回传的资料是以阵列型式
,故利用map对每个资料做处理,利用replace方法去改变每笔符合资料,关键字的颜色
,并回传一个以正规表达式处理好的人口数,然后将整个阵列,用join方法切割并合併
成一个字串,最后放进ul里面即可
完整结果如下图