Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

搜索词高亮 #34

Open
cobish opened this issue Sep 22, 2017 · 2 comments
Open

搜索词高亮 #34

cobish opened this issue Sep 22, 2017 · 2 comments
Labels

Comments

@cobish
Copy link
Owner

cobish commented Sep 22, 2017

搜索框输入搜索词,ajax 请求,将返回的数据通过模板引擎生成 html 代码插入 DOM。

现在需要将搜索到的内容里的搜索词高亮,也就是添加一个带颜色的 span 标签。

思路一

先将 html 插入 DOM,再通过 DOM 查找,替换,再插入。

缺点:DOM 操作太多,消耗性能。

思路二

通过 document.createDocumentFragment() 创建文档片段,在片段上进行替换操作后,最终再添加到 DOM 树上。

<html>
  <body>
    <div id="app"></div>
  </body>
</html>
var source = `
	<div>
  	<span class="test">正大光明</span>
  </div>
`;

var frag = document.createDocumentFragment();
var tmp = document.createElement('body');

tmp.innerHTML = source;
frag.appendChild(tmp);

var ele = frag.querySelector('.test');
var eleVal = ele.innerHTML;
ele.innerHTML = eleVal.replace('光', '<i>光</i>');

document.getElementById('app').append(frag);

优点:避免了高耗性能的 DOM 操作,而是在内存中操作。

缺点:代码实现起来还是有些麻烦。

思路三

正则。

开始想着如何去替换模板引擎生成的 html 字符串,但伴随的风险也有可能替换了标签内的字符串(即 <> 内的字符串)。

想不到匹配的正则。于是换思路,先匹配所有,包括标签内的字符串,然后再正则匹配回标签内的字符串。

沿着这个思路,写出的正则既要能匹配到标签内的字符串,又要不能匹配到标签外的字符串。

正则 (?=exp) : 匹配 exp 前面的位置,举些例子:

// 将 xxoo 匹配成 c
var str = 'xxoo(axxoob)xxoo';

str.replace(/xxoo/g, 'c');
// 输出: c(acb)c;

str.replace(/xxoo/g, 'c');
// 输出:xxoo(axxoob)xxoo ,不变

str.replace(/xxoo(?=[^(]*\))/g, 'c');
// 输出:xxoo(acb)xxoo

上面的正则有个缺点,那就是括号内再括号的话,它只匹配最内层的,而忽略的外层的匹配。所以头疼,因为标签肯定会再嵌套标签的。

思路三,无法实现。

思路四

按照思路三的走法,因为我们匹配的属于特殊的情况,即都是 html 片段,所以能知道都是标签代码,而代码中属于非标签部分都是以 > 开头, < 结尾(根部至少有标签包住),并且不嵌套。所以依旧可以使用思路三的正则,只不过从想匹配 <> 内的字符串转变成替换 >< 内的字符串。

var str = `
  <div>
      <span class="光明">
      	<span>光明<span>
      </span>
  </div>
`;
        
var keyWord = '光';
var reg = new RegExp(keyWord + '(?=[^\\>]*\\<)', 'g');
var result = str.replace(reg, '<i>' +keyWord+  '</i>');

console.log(result);

思路四行得通。

优点:避免了麻烦的 DOM 方法操作,代码简介。

缺点:正则有点难度,而且思路比较难理解。

纠正(2017-11-16)

以上的思路都是在拼接成 html 片段后才进行高亮查找的。其实,如果是一段文字,可以先将需要高亮的词替换成添加了标签的高亮词,然后再拼接成 html 片段插入即可。

@cobish cobish added the 前端 label Sep 22, 2017
@lcl-101
Copy link

lcl-101 commented May 31, 2018

不错

@cobish
Copy link
Owner Author

cobish commented May 31, 2018

@lcl-101 多谢赏脸 🌹

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants