一、目的
模拟浏览器ctrl+F功能,对输入内容进行搜索,并高亮显示
输入想要搜索的内容:
对应内容高亮显示:
二、实现
成功实现:
<body>
<button>点击搜索</button>
<input class="hidden" type="text">
<div class="content">
<p>在这个宁静的夜晚,月光洒在静谧的湖面上,波光粼粼。</p>
<p>湖边的柳树随风轻摆,仿佛在诉说着古老的传说。</p>
<p>远处,偶尔传来几声蛙鸣,伴随着夜风的轻吟,构成了一首自然的交响乐。</p>
<p>散步的人们享受着这份宁静,脸上洋溢着平和的微笑。</p>
<p>这是,一个充满希望与梦想的世界,每个人都在这片星空下寻找着自己的位置。</p>
</div>
</body>
<script>
const btn = document.querySelector('button');
const input = document.querySelector('input');
const content = document.querySelector('.content');
const html = content.innerHTML;
btn.addEventListener('click', () => {
if(input.classList.contains('hidden')){
input.classList.remove('hidden');
} else {
input.classList.add('hidden');
}
})
//按下Ctrl+F,搜索框出现
window.addEventListener('keydown',(event)=>{
if(event.ctrlKey && event.keyCode == 70){
if(input.classList.contains('hidden')){
input.classList.remove('hidden');
}
}
})
//匹配高亮
input.addEventListener('input',()=>{
console.log(input.value);
//先还原回初始状态
content.innerHTML = html;
//获取输入内容
const value = input.value;
//有输入内容
if(value){
let regValue = new RegExp(value, "g");//匹配value
let regHtml = new RegExp("\<.*?\>", "ig");//匹配html元素
let htmls = content.innerHTML.match(regHtml); //存放html元素的数组
let text = content.innerHTML;
text = text.replace(regHtml, '{~}'); //替换html标签
//替换value
text = text.replace(regValue, `<span class="highlight">${value}</span>`);
htmls.forEach(html=>{
text = text.replace(/{~}/g,html);
})
content.innerHTML = text;
}
})
</script>
<style>
.highlight{
background-color: #ffc400;
}
.hidden{
display: none;
}
</style>
错误实现:
<body>
<button>点击搜索</button>
<input class="hidden" type="text">
<p>在这个宁静的夜晚,月光洒在静谧的湖面上,波光粼粼。</p>
<p>湖边的柳树随风轻摆,仿佛在诉说着古老的传说。</p>
<p>远处,偶尔传来几声蛙鸣,伴随着夜风的轻吟,构成了一首自然的交响乐。</p>
<p>散步的人们享受着这份宁静,脸上洋溢着平和的微笑。</p>
<p>这是一个充满希望与梦想的世界,每个人都在这片星空下寻找着自己的位置。</p>
</body>
<script>
const btn = document.querySelector('button');
const input = document.querySelector('input');
btn.addEventListener('click', () => {
if(input.classList.contains('hidden')){
input.classList.remove('hidden');
} else {
input.classList.add('hidden');
}
})
//按下Ctrl+F,搜索框出现
window.addEventListener('keydown',(event)=>{
if(event.ctrlKey && event.keyCode == 70){
if(input.classList.contains('hidden')){
input.classList.remove('hidden');
}
}
})
input.addEventListener('input',()=>{
const body = document.querySelector('body');
if(input.value){
const value = input.value;
const reg = new RegExp(value, "g");
const html = content.innerHTML;
content.innerHTML = html.replace(reg, `<span class="highlight">${value}</span>`);
}
})
</script>
1.直接更改body的innerHTML,导致绑定在输入框上的input事件失效
这是因为,修改body的innerHTML相当于重写了body里面的输入框,这就相当于创建了另外一个dom对象,之前渲染的dom跟这个新的dom对象没有关系,所以就导致了事件的丢失。
2.每次不还原初始状态,导致搜索内容改变后,原来的高亮依然存在
所以要在一开始记录初始innerHTML,每次input事件触发后要先还原回初始状态。
3.没有考虑到标签名,直接匹配innerHTML当输入英文时,可能会匹配到标签名
所以先将标签替换成其他内容并将所有标签保存在一个数组中,匹配完成后,再将这部分内容换回原来的标签。