承接上文,这是第6个案例:
附上项目链接: https://github.com/wesbos/JavaScript30
这个主要是要实现在给定的json里匹配出搜索框里的city or state,然后把人口加上千分号,下面是我加了注释的源码:
<script> const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json'; const cities = []; fetch(endpoint) .then(blob => blob.json()) // 扩展运算符(…)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中 .then(data => cities.push(...data)); function findMatches(wordToMatch, cities) { return cities.filter(place => { // here we need to figure out if the city or state matches what was searched const regex = new RegExp(wordToMatch, 'gi'); return place.city.match(regex) || place.state.match(regex) }); } function numberWithCommas(x) { // 给数字加千分符 return x.toString().replace(/B(?=(d{3})+(?!d))/g, ','); /* /B(?=(d{3})+(?!d))/g 这个正则,我正则不太好,所以一开始不知道是什么意思,网上看了下,现在已经完全理解了 1.元字符B,其实真正要匹配的是这个,就像语文里面,你是一个和蔼可亲的人,最后要匹配的是人,和蔼可亲是条件,这里其实也是后面一串是条件,我试了下 var a = 123456; a.toString().replace(//g, 'aa') //"aa123456aa" 匹配的是单词两边的这些空隙 a.toString().replace(/B/g, 'aa') //"1aa2aa3aa4aa5aa6" B和是相反的,不属于的位置就会被B匹配到 2.先行断言?=,我们再来看后面这个,他的作用,举个例子吧,x(?=y),跟着先行断言后面这个的前面那个就会被匹配到,如:xyz,这里x会被匹配,y不会被匹配, 匹配的是先行断言前面的.在这个正则里面,先行断言后面跟着(d{3})+,其实是找寻后面跟了3的倍数个数字的位置,像对于一串字符12345来说, 这个正则表达式匹配1和2,2和3这两位置,因为这两个位置后面都满足跟了3的倍数个数字(234和345),很显然还不满足我们的要求,我们是只要2和3这个位置 3.后行断言?!,我们想要的情况,是三个三个数字,但是后面不会再跟着数字的情况,?!d这个就是这个意思 总结: (?=(d{3})+(?!d))代表的是:后面需要跟3的倍数个数字,且在这(3的倍数个数字)之后不能再有数字了,他可以是小数点.或字符串尾。 如12345.67中只有2和3之间的位置满足我们上述的条件。我们只需要指出这个位置,然后将它替换成逗号。 备注:其实后面那个后行断言也可以直接用,只要他后面是字符边界,也可以匹配 */ } function displayMatches() { const matchArray = findMatches(this.value, cities); 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(''); suggestions.innerHTML = html; } const searchInput = document.querySelector('.search'); const suggestions = document.querySelector('.suggestions'); searchInput.addEventListener('change', displayMatches); //这个keyup事件貌似没什么用 searchInput.addEventListener('keyup', displayMatches); </script>