前端实现高亮划词
前言
前端实现文字高亮划词。这个功能一般都是一些类似笔记产品上才会出现的一个功能,通过添加指定的关键字进行高亮显示。我这两天也做了一个出来,名字叫ohlight
,实现的方式不是网上那些复杂的方式,很简单的一个方式,感兴趣的朋友可以看下方地址。
项目地址
// pnpm
pnpm i ohlight
// npm
npm i ohlight
// yarn
yarn add ohlight
使用效果
我们先看看以下使用效果,高亮样式是全场支持自定义的哈,这里我使用的是默认的样式。
实现
采用web Components
实现组件,这样就可以直接跨框架、无框架运行了,简直高效一套代码运行任何框架。感兴趣的朋友可以看MDN。
高亮划词的地方也很简单,不要看文件有点多,实际都是打辅助的,核心的就只有下面的代码。
for(let keyword of keywords){
c = c.replace(new RegExp(keyword, 'g'), `<mark style="${s}">${keyword}</mark>`)
}
现在我们开始实现这个组件吧,本文将采用和ohlight
组件一样的方式。
本篇文章是基于web Components
进行编写,还不了解的朋友可以去看一下MDN。
注:本文会简单实现ohlight
组件的亮词功能,其他功能大家可以去gitee
和github
上看源码。👏欢迎大家star、issue等。
搭建基础框架
我们直接新建一个OHLight
的类,然后注册,组件内部进行挂载。这里我们写OHLight
类的时候需要继承HTMLElement
。
class OHLight extends HTMLElement {}
customElements.define('o-hlight', OHLight)
export default OHLight
然后在constructor
中需要调用super()
,这一步必不可少。
constructor(){
super()
}
我们在类中添加一个renderer
渲染函数。
renderer () {}
我们的基础框架就搭建好了,下面是目前步骤的完整代码:
class OHLight extends HTMLElement {
constructor(){
super()
}
renderer () {}
}
customElements.define('o-hlight', OHLight)
export default OHLight
渲染
这一步我们需要将我们的组件渲染在页面上。这一步的操作全程都在renderer
方法中。
我们先让我们的组件可以根据dom
操作而操作。这里当mode
为open
是可以操作的,为closed
则该dom
不可操作。
renderer () {
this.attachShadow({
mode: 'open'
})
}
我们创建一个div
盒子然后并挂载到我们的shadowRoot
影子节点上,当然你也可以创建其他的标签;并给他插入内容;然后添加组件。
const node = document.createElement('div')
node.innerHTML = '桃小瑞'
this.shadowRoot?.appendChild(node)
可以在constructor
中调用我们的renderer
方法。
接下来就到了奇迹的时刻了,我们引入组件,并在页面上使用。
此时的所有的完整代码如下:
class OHLight extends HTMLElement {
constructor(){
super()
this.renderer()
}
renderer () {
this.attachShadow({
mode: 'open'
})
const node = document.createElement('div')
node.innerHTML = '桃小瑞'
this.shadowRoot?.appendChild(node)
}
}
customElements.define('o-hlight', OHLight)
export default OHLight
页面上就会出现我们的组件内容。
获取属性并设置高亮
这一步我们将获取我们传递的文本内容、关键词进行高亮显示。
我们以content
属性来做我们的文本内容传参。
我们需要获取我们组件中的content
属性。并通过innerHTML
将内容插入到页面中去
let content = this.attributes.content
node.innerHTML = `${content.value}`
组件内容:
效果图:
这里我们需要将constructor
中调用renderer
的方法移动到connectedCallback
生命钩子内,不然会拿不到内容。
connectedCallback(){
this.renderer()
}
页面上已经渲染出来了我们的内容。现在我们进行关键词获取 + 渲染。
跟我们获取内容是一样的方法,我们获取keywords
关键词列表。
let keywords = this.attributes.keywords
现在我们已经获取到了关键词列表,我们对内容进行检查和替换。
声明一个handle
的方法,并将文本内容和关键字传进去,用来处理我们的高亮词汇。这个方法返回的内容就是我们已经处理好的文本内容,可以直接插入显示。
node.innerHTML = this.handle((content.value || ''), (keywords.value || ''))
handle (content, keywords) {
let keywordList = []
if(keywords.includes(',')){
keywordList = keywords.split(',')
}else{
keywordList = [keywords]
}
}
上面我们在handle
方法中进行了关键词组处理,多个关键词使用(,)逗号
隔开,然后进行判断、切割。
for(let keyword of keywordList){
c = c.replace(new RegExp(keyword, 'g'), `<mark>${keyword}</mark>`)
}
这里我们对已经处理好的关键词进行循环,在循环的过程中我们使用new RegExp(keyword, 'g')
正则进行替换,将获取到的关键字替换为用mark
标签装起来的字符串<mark>${keyword}</mark>
。
看一下效果:
组件内容:
这样我们就实现好了。
完整代码:
class OHLight extends HTMLElement {
constructor(){
super()
}
renderer () {
this.attachShadow({
mode: 'open'
})
const node = document.createElement('div')
let content = this.attributes.content
let keywords = this.attributes.keywords
node.innerHTML = this.handle((content.value || ''), (keywords.value || ''))
this.shadowRoot?.appendChild(node)
}
handle (content, keywords) {
let c = content
let keywordList = []
if(keywords.includes(',')){
keywordList = keywords.split(',')
}else{
keywordList = [keywords]
}
for(let keyword of keywordList){
c = c.replace(new RegExp(keyword, 'g'), `<mark>${keyword}</mark>`)
}
return c
}
// 当自定义元素第一次被连接到文档 DOM 时被调用
connectedCallback(){
this.renderer()
}
}
customElements.define('o-hlight', OHLight)
export default OHLight
生命钩子说明补充
web components
有四个状态的生命钩子,分别如下:
connectedCallback
:当自定义元素第一次被连接到文档 DOM 时被调用;disconnectedCallback
:当自定义元素与文档 DOM 断开连接时被调用;adoptedCallback
:当自定义元素被移动到新文档时被调用;attributeChangedCallback
:当自定义元素的一个属性被增加、移除或更改时被调用。
我们想实现自定义样式的话直接给mark
标签添加样式就可以了。
关于响应式的问题,ohlight
是支持响应式的修改内容/关键字的,这里我是使用的attributeChangedCallback
进行监听。
最后
以上就是前端实现高亮划词的一个文章。
欢迎大家下载使用ohlight 高亮划词组件
。
转载自:https://juejin.cn/post/7179794611995902011