解析
结构部分如下
代码语言:javascript复制<template>
<div>
<span
:class="index%2!==0?'hightLight':''"
v-for="(item,index) in textData"
:key="index"
>{{item}}</span>
</div>
</template>
基本原理就是将传入的str按照正则的规则进行切割,偶数部分负责高亮,奇数部分负责正常显示
如:
str与reg分别为
let str = "高亮几个词语出来好不好";
let reg = /(高亮|词语)/g;
将该部分切割为如下数组
"高亮几个词语出来好不好" ---》 '', '高亮', '几个', '词语', '出来好不好' ----》
知道了基本原理,我们再来看一下代码
代码语言:javascript复制 let str = "高亮几个词语出来好不好";
let reg = /(高亮|词语)/g;
let result = {};
let currentIndex = 0, returnData = [];
while ((result = reg.exec(str))) {
returnData.push(str.slice(currentIndex, result.index));
returnData.push(result[1]);
currentIndex = result.index result[0].length;
}
if (str.length > currentIndex) {
returnData.push(str.slice(currentIndex, str.length));
}
console.log(returnData);
this.textData = returnData;
代码关键在于理解reg.exec,了解这个api的可以直接跳到提取关键字并分组
正则api——exec
理解了这个例子,也就基本理解了其他的例子
我们这样规定,将被两个#和一个空格包围的内容进行高亮即## 内容 ##时,内容要被提取出来并高亮,首先要对其进行分组
代码语言:javascript复制"1212## 4455 #### 0011 ##44488## 000000 ##"就会被分为
['1212', '4455', '', '0011', '44488', '000000']
高亮文本与普通文本间隔排序
先来看看下面这部分代码
代码语言:javascript复制let str = "1212## 4455 #### 0011 ##44488## 000000 ##";
let reg = /##s (.*?)s ##/g;
console.log(reg.exec(str));
console.log(reg.exec(str));
console.log(reg.exec(str));
console.log(reg.exec(str));
执行结果如下
reg.exec执行
第一次的时候会从字段中找到第一个匹配的字段(## 4455 ##),
第二次:会在第一次匹配的位置后找到第二个匹配的字段(## 0011 ##),
第三次:会在第二次匹配的位置后找到第三个匹配字段(## 000000 ##)
第四次时,剩余的字符已经没有了匹配所有返回null
也就是说,在null之后的执行结果,都是循环之前的执行结果,所以咱们在执行结果为null时即可停止
接下来看看执行具体的执行结果
代码语言:javascript复制0: "## 4455 ##"
1: "4455"
groups: undefined
index: 4
input: "1212## 4455 #### 0011 ##44488## 000000 ##"
length: 2
返回的是一个数组,并带有几个字段属性
结合一下其正则'0'是拿匹配到正则规则的值,'1'则是匹配到在正则里第一个被括号包起来的值
,这个lenth你可以粗糙的理解为需要提取的(即有几个括号)数量 1(这个指的是能匹配到的整体)
至于为什么是一样的还要用括号括起来,这个后面会说
知道原理之后我们来看看如何提取关键字并分组
提取关键字并分组
提取关键字并分组
首先我们清楚的看到,通过正则,他会给出三个有用的信息
第一个是匹配到的正则规则中的值
第二个是可以拿到我们想要提取出来 即用括号括起来的值
第三个是该值所在的index
我们一步一步来
分成这种结构,
也就是每次exec执行不为null时都做一次区分, 将匹配到的值前方位置提取作为普通字符串,再把当前的关键字提取作为高亮字符串,如下:
比如第一次匹配时,拿到的值是这样的
第二次匹配
代码语言:javascript复制/*
0: "## 4455 ##"
1: "4455"
groups: undefined
index: 4
input: "1212## 4455 #### 0011 ##44488## 000000 ##"
length: 2
*/
这里index为4,将下标为0-4的字符提取为普通数组,而匹配到的字符串4455作为高亮字符
此时数组为'1212','4455'
第二次匹配
代码语言:javascript复制0: "## 0011 ##"
1: "0011"
groups: undefined
index: 14
input: "1212## 4455 #### 0011 ##44488## 000000 ##"
length: 2
普通字符串应下标为为14-14即空字符串,高亮字符为匹配到的0011
此时数组为'','0011'
这里需要明确两个14分别是怎么来的
第一个14是上一次匹配返回值的 index 上次匹配到字符串字符串## 4455 ##的长度
第二个14是本次配到的index,
可能这时还有点懵,看这最后一次匹配,你应该就理解了
第三次匹配
代码语言:javascript复制0: "## 000000 ##"
1: "000000"
groups: undefined
index: 29
input: "1212## 4455 #### 0011 ##44488## 000000 ##"
length: 2
普通字符串应是下标为24-29即44488,高亮字符为000000
此时数组为'44488','000000'
同样需要明确24,29分别是怎么来的
第一个是上一次匹配返回值的 index 上次匹配到字符串### 0011 ##的长度
第二个则是本次匹配到的index 29
至此 我们用一个while循环将其包裹,利用上面的规则把对应的值push到数组中,并用一个值缓存上一次的index就可以得到我们的目标数组
代码语言:javascript复制 let str = "1212## 4455 #### 0011 ##44488## 000000 ##";
let reg = /##s (.*?)s ##/g;
let result = {};
let currentIndex = 0,
returnData = [];
while ((result = reg.exec(str))) {
console.log(result);
returnData.push(str.slice(currentIndex, result.index));
returnData.push(result[1]);
currentIndex = result.index result[0].length;
}
// 最后一次匹配的高亮词后可能还有没push到数组中的值
if (str.length > currentIndex) {
returnData.push(str.slice(currentIndex, str.length));
}
console.log(returnData); // ['1212', '4455', '', '0011', '44488', '000000']
this.textData = returnData;
完整vue代码
代码语言:javascript复制<template>
<div>
<span
:class="index%2!==0?'hightLight':''"
v-for="(item,index) in textData"
:key="index"
>{{item}}</span>
</div>
</template>
<script>
export default {
data() {
return {};
},
created() {
this.init();
},
methods: {
init() {
// let str = "实现搜索词高亮 - 百度文库";
// let reg = /([高亮词文])/g;
// let str = "高亮几个词语出来好不好";
// let reg = /(高亮|词语)/g;
let str = "1212## 4455 #### 0011 ##44488## 000000 ##";
let reg = /##s (.*?)s ##/g;
let result = {};
let currentIndex = 0,
returnData = [];
while ((result = reg.exec(str))) {
console.log(result);
returnData.push(str.slice(currentIndex, result.index));
returnData.push(result[1]);
currentIndex = result.index result[0].length;
}
if (str.length > currentIndex) {
returnData.push(str.slice(currentIndex, str.length));
}
console.log(returnData);
this.textData = returnData;
}
}
};
</script>
<style>
.hightLight {
color: red;
}
</style>
源码附件已经打包好上传到百度云了,大家自行下载即可~
链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27
提取码: yu27
百度云链接不稳定,随时可能会失效,大家抓紧保存哈。
如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~
开源地址
码云地址:
http://github.crmeb.net/u/defu
Github 地址:
http://github.crmeb.net/u/defu