跳到主要内容

批量添加和模糊搜索

阅读需 4 分钟

IFE 的一份作业

任务要求

  • 允许一次批量输入多个内容,格式可以为数字、中文、英文等,可以通过用回车,逗号(全角半角均可),顿号,空格(全角半角、Tab等均可)等符号作为不同内容的间隔

  • 增加一个查询文本输入框,和一个查询按钮,当点击查询时,将查询词在各个元素内容中做模糊匹配,将匹配到的内容进行特殊标识,如文字颜色等。举例,内容中有abcd,查询词为ab或bc,则该内容需要标识

  • 具体要求地址:http://ife.baidu.com/course/detail/id/107

功能预览

图片

在线体验:在线体验

代码地址:https://github.com/evenIfAlsoGo/IFE/tree/master/binbin/06

解决思路

1. 允许一次批量输入多个内容

单次添加,按一次按钮,创建一个结点。

多次添加,按一次按钮,根据条件,创建多个结点。

创建结点是同一种操作,那么使用循环来解决“多个”的问题即可。

但是循环的条件是什么,也就是什么时候该创建这个结点,什么时候该创建下一个结点,什么时候结束?

由题意可知,只要此时的字符为数字、字母或中文时,就是一个开始,反之就是一个结束。

那么我们的目的就非常明了了,获取所有由数字、字母或中文组成的连续数据。

正则表达式可以直接解决这个问题:

val.match(/[0-9A-Za-z\u4e00-\u9fa5]+/g)

此时 val 为输入框的数据,match 方法会返回一个包含查找结果的数组,这个数组存有符合条件的所有数据,以其为基准直接创建多个结点即可。

代码对比:(前单后批次,已删除与主题无关的代码)

leftIn.onclick = function () {    
let val = addNum.value /*获取数据*/
let newNode = createNewNode(val) /*创建结点*/
...
}
leftIn.onclick = function () {    
let val = addWord.value
let words = val.match(/[0-9A-Za-z\u4e00-\u9fa5]+/g)
for(let i=0; i<words.length; i++) {
let newNode = createNewNode(words[i])
...
}
}

2. 模糊查询

最初的想法是,删除所有结点,再新建所有结点,在新建的过程中判断是否符合查询条件,进行高亮显示。但这样会造成高耦合:新建结点和其是否符合条件并无关联,无论条件怎样,这个结点一定是存在的,数据是一定在的,变的只是样式。

那么获取到所有结点,然后对结点内的 innerHTML 改动即可。

代码浏览:

search.onclick = function(){    
/*获取查询数据*/
let text = searchText.value
/*获取所有结点的集合*/
let nodes = showWord.getElementsByTagName("div")
/*遍历每个结点,对其进行数据匹配*/
for(let i=0; i<nodes.length; i++) {
let reg = new RegExp(text, "g")
/*textContent是只获取字符,不包含html代码,而innerHTML包含html代码*/
nodes[i].innerHTML = nodes[i].textContent.replace(reg, "<span class='sign'>" + text + "</span>" )
}
}

注意正则表达式:

nodes[i].textContent.replace(reg, "<span class='sign'>" + text + "</span>" )

总结

其实解决两个问题的核心是,正则表达式

最开始我也使用笨办法,比如两个循环,来判断数据匹配,但是突然想到正则,我只学过一点,并没有实际应用过几次,这次也算是给这个领域跨进了一步。这个工具我是极其推荐学习的,效率杠杠的。

此外需注意低耦合,一个方法只完成一个件事情。

今天开始写的时候还有些犹豫,有思路但是觉得比较麻烦,幸好坚持了,竟然没有添加多少代码就完成了之前从未实现过的功能。不能想着一口吃成大胖子哟。

暂时未加入评论功能,请在对应公众号文章下或 GitHub Issues下留言反馈。