注册
web

前端实现点击选词功能

今天有一个需求,点击选中某个英文单词,然后对这个单词做一些处理,例如高亮背景、查看一些详细信息等等,今天简单实现了一下,效果如下:(支持移动端,chrome和sarafi浏览器均能正常使用。语言🚀 vue3 + typescript)


highlight.gif


选词


由于要动态添加给某些单词动态添加一些标签,我们这里可以考虑使用v-html


首先我们先编写一下简单的结构


<script setup lang="ts">
</script>

<template>
<div class="container" v-html="shortArticle"></div>
</template>


<style>
.container {
font-size: 18px;
}
</style>

然后,我们将需要处理的短文变换为span标签包裹,这里的思路是按照空格划分,然后添加span结构,最后拼接到一起返回。这里有一些边缘条件要考虑,比如can't(whichyes!等等,按照空格划分出来的数据有一点问题。


截屏2023-04-19 20.48.19.png


如果不做处理的话,一些标点符号也会高亮出来,就不太正确了。下面是处理逻辑,整体比较简单,就不解释了。


function addElementSpan(str: string): string {
return str
.split(' ')
.map((item) => {
const { start, word, end } = getWord(item)
return `${start}<span>${word}</span>${end} `
})
.join('')
}

function getWord(str: string) {
let word = ''
let start = ''
let end = ''
let j = str.length - 1
let i = 0

while (i < str.length) {
if (/^[a-zA-Z]$/.test(str[i])) {
break
}
start = start + str[i]
i += 1
}

while (j >= 0) {
if (/^[a-zA-Z]$/.test(str[j])) {
break
}
end = str[j] + end
j -= 1
}

word = str.slice(i, j + 1)

// 处理数字
if (!word && start === end) {
start = ''
}

return {
start,
word,
end
}
}

现在我们来实现效果


<script setup lang="ts">
import { computed } from 'vue'
import { addElementSpan } from './utils'

const str = `It works fine if you move the navbar outside the header. See below. For the reason, according to MDN: The element is positioned according to the normal flow of the document, and then offset
relative to its flow root and containing block based on the values of top, right, bottom, and
left. For the containing block: The containing block is the ancestor to which the element is
relatively positioned So, when I do not misunderstand, the navbar is positioned at offset 0
within the header as soon as it is scrolled outside the viewport (which, clearly, means, you
can't see it anymore).`


const shortArticle = computed(() => {
return addElementSpan(str)
})

function setColor(event: any) {
// console.log(event.target.innerText) 获取选中的文本
event.target?.classList.add('word_highlight')
}
</script>

<template>
<div class="container" @click="setColor($event)" v-html="shortArticle"></div>
</template>


<style>
.word_highlight {
background-color: red;
}
</style>


在父亲元素上添加点击事件,触发事件点击之后,调用setColor函数,高亮背景(添加class)


不过有一点小小的问题,点击div的空白区域或者非英文单词区域会直接整个背景变成红色,控制台打印event.target.innerText可以发现它的值为整个文本,所以我们可以根据判断打印的文本长度和需要设置的文本长度是否一致来解决这个问题。(ps:⬆️面的示例代码str字符串使用了反引号 模板字符串 ,直接使用下面会影响结果)


function setColor(event: any) {
// console.log(event.target.innerText)
if(str !== event.target.innerText){
event.target?.classList.add('word_highlight')
}
}

对于event.target不太了解的伙伴可以看这篇文章 ➡️ Event.target - Web API 接口参考 | MDN (mozilla.org)


(和event.target类似的还有一个属性event.currentTarget,不太了解的伙伴可以看下这篇文章 ➡️ Event.currentTarget - Web API 接口参考 | MDN (mozilla.org),它俩的区别是event.target指的是事件触发的元素,而event.currentTarget指的是事件绑定的元素)


功能拓展


这里只是演示了一下比较简单的背景高亮效果,有需求的伙伴可以自己拓展一下。


比如类似于掘金的拼写错误提示框


截屏2023-04-19 21.16.20.png


如果要实现滑动选词的话,可以参考这个博主的文章 ➡️ 鼠标选中文本划词高亮、再次选中划词取消高亮效果


作者:笨笨狗吞噬者
来源:juejin.cn/post/7223733256688025661

0 个评论

要回复文章请先登录注册