忽略html标签(特殊&#等。替换过滤处理),搜索关键字并高亮显示,带锚点定位(实现ctrl+F)的功能。两种方法(正则表达式,range方法)

目录

方法1:使用纯正则替换

1.重点代码:

2.普通版完整函数(不带不可见字符&#情况):

3.进阶版完整函数(word导入后或者有时候带了&#不可见字符转文字的情况下):

4.decoders函数:

5.锚点部分:

6.锚点定位的使用:

7.定位的主要代码在

8.锚点完整代码: 

方法2:使用文本替换锚点后。使用range方法实现切换高亮。(防止数据太多。导致上下切换高亮卡顿)

1.替换&#不可见生成的字符(例如🳃;等之类的)并替换掉标签。使所有关键词高亮。

2.高亮的方法函数(默认第一个高亮):

  3.切换上一个和下一个(不卡顿)

 文章内容大致为:通过v-html渲染的页面。

data中的某些值:

关于方法2的知识点参考:http://t.csdn.cn/DT92m


方法1:使用纯正则替换

1.重点代码:

这边就是忽略标签直接匹配内容的部分,val为你搜索的内容文字

  const reg = new RegExp(val, 'g')
            this.detailLi.content = this.detailLi.content.replace(new RegExp('(?=\>).+?(?=\<)', 'g'), function (str) {
              const reg1 = new RegExp('(?=>).+', 'g')
              return str.replace(new RegExp('(>).+', 'g'), function (str2) {
                return str2.replace(reg1, function (str1) {
                  return str1.replace(reg, '<em style="background-color: yellow">' + val + '</em>')
                })
              })
            })

2.普通版完整函数(不带不可见字符&#情况):

test就是你搜索按钮点击事件,val既搜索框的内容

     test (val, x) {
          this.pickNum = 0
          if (val !== '') {
            if (this.searData !== '') {
              this.detailLi.content = this.searData
            } else {
              this.searData = this.detailLi.content
            }
            const reg = new RegExp(String(val), 'g')
            //正则校验除了标签之外
            this.detailLi.content = this.detailLi.content.replace(new RegExp('(?=\>).+?(?=\<)', 'g'), function (str) {
              const reg1 = new RegExp('(?=>).+', 'g')
              return str.replace(new RegExp('(>).+', 'g'), function (str2) {
                return str2.replace(reg1, function (str1) {
                  //这边是判断乱码过滤(&#36830;&#25509;&#25968;&#25454;&#24211;&#25104;&#21151;&#65281;)正则校验除了这种的之外
                  return str1.replace(new RegExp('^((?!(?=\&).+?(?=\;)).)*$','g'),function (str0) {
                    return str0.replace(reg, `<span id="test_idconese" style="background-color: #00a4ff">${val}</span>`)
                  })
                })
              })
            })
            const value2 = new RegExp('test_idconese', 'gi')
            this.allData = this.detailLi.content.match(value2)
            if (this.allData && this.allData.length > 0) {
              this.allData.forEach((item, index) => {
                this.detailLi.content = this.detailLi.content.replace('test_idconese', `test_${index}idconese`)
              })
            }
            this.detailLi.content = this.detailLi.content.replace('<span id="test_0idconese" style="background-color: #00a4ff">', '<span id="test_0idconese" style="background-color: red">')
          } else {
            this.allData = []
          }
          if (x) {
            if (this.searData !== '') {
              this.detailLi.content = this.searData
            } else {
              this.searData = this.detailLi.content
            }
          }
        },

3.进阶版完整函数(word导入后或者有时候带了&#不可见字符转文字的情况下):

 test为完整函数:里面的decoders事件写在后面。

 test (val, x, keyWord) {
          const that = this
            this.pickNum = 0
            if (val !== '') {
              if (this.searData !== '') {
                this.detailLi.content = this.searData
              } else {
                this.searData = this.detailLi.content
              }
              const reg = new RegExp(val, 'g')
              // 正则校验先乱码过滤(&#36830;&#25509;&#25968;&#25454;&#24211;&#25104;&#21151;&#65281;)正则校验除了这种的之外
              this.detailLi.content = this.detailLi.content.replace(new RegExp('(?=\>).+?(?=\<)', 'g'), function (dades) {
                if (dades.indexOf('&#') !== -1) {
                  return dades.replace(new RegExp('((?=\&).+?)(?=\;)+\;', 'g'), function (s) {
                    const tihuan = that.decoders(s)
                    return dades.replace(dades, `${tihuan}`)
                  })
                } else {
                  return dades
                }
              })
              // 正则校验除了标签之外
              this.detailLi.content = this.detailLi.content.replace(new RegExp('(?=\>).+?(?=\<)', 'g'), function (str) {
                const reg1 = new RegExp('(?=>).+', 'g')
                return str.replace(new RegExp('(>).+', 'g'), function (str2) {
                  console.log(str2, 'str22')
                  return str2.replace(reg1, function (str1) {
                    console.log(str1.indexOf('&#'), str1, 'str2')
                    return str1.replace(reg, `<span id="test_idconese" style="background-color: #00a4ff">${val}</span>`)
                    // if (str1.indexOf('&#') !== -1) {
                    //   return str1.replace(new RegExp('(?<=;)[^&]+(?=&)', 'g'), function (str0) {
                    //     return str0.replace(reg, `<span id="test_idconese" style="background-color: #00a4ff">${val}</span>`)
                    //   })
                    // } else {
                    //   // 这边是判断乱码过滤(&#36830;&#25509;&#25968;&#25454;&#24211;&#25104;&#21151;&#65281;)正则校验除了这种的之外
                    //   return str1.replace(new RegExp('^((?!((?=\&).+?)(?=\;)).)*$', 'g'), function (str0) {
                    //   })
                    // }
                  })
                })
              })
              const value2 = new RegExp('test_idconese', 'gi')
              this.allData = this.detailLi.content.match(value2)
              if (this.allData && this.allData.length > 0) {
                this.allData.forEach((item, index) => {
                  this.detailLi.content = this.detailLi.content.replace('test_idconese', `test_${index}idconese`)
                })
              }
              this.detailLi.content = this.detailLi.content.replace('<span id="test_0idconese" style="background-color: #00a4ff">', '<span id="test_0idconese" style="background-color: red">')
              this.$nextTick(function () {
                if (this.$el.querySelector('#test_0idconese')) {
                  this.$el.querySelector('#test_0idconese').scrollIntoView({
                    behavior: 'smooth',
                    inline: 'nearest',
                  })
                }
              })
            } else {
              this.allData = []
            }
            if (x) {
              if (this.searData !== '') {
                this.detailLi.content = this.searData
              } else {
                this.searData = this.detailLi.content
              }
            }
        },

4.decoders函数:

&#特殊字符转文字的方法:

  // &#编码转文字
        decoders (str) {
          var tempArr = str.split(/\&#|\;/)
          console.log(str, tempArr, 'tem')
          var tmpLength = tempArr.length
          var str = ''
          for (var i = 0; i < tmpLength; i++) {
              if (tempArr[i] != '') {
              str += String.fromCharCode(tempArr[i])
            }
          }
          return str
            },

5.锚点部分:

1.先对所有匹配的内容添加统一相同的ID:

 return str1.replace(reg, `<span id="test_idconese" style="background-color: #00a4ff">${val}</span>`)

2.在通过match去获取有几个id为test_idconese的标签。并且遍历修改每个标签的ID添加index区别索引,用来后面锚点定位使用。

const value2 = new RegExp('test_idconese', 'gi')
            this.allData = this.detailLi.content.match(value2)
            if (this.allData && this.allData.length > 0) {
              this.allData.forEach((item, index) => {
                this.detailLi.content = this.detailLi.content.replace('test_idconese', `test_${index}idconese`)
              })
            }

6.锚点定位的使用:

这边的pickUp和pickDown就是ctrl+F中的下一个关键词和上一个关键词,我这边是自己写了个按钮点击事件去执行它,num写着玩的。没有用。

7.定位的主要代码在

根据id去定位到锚点所在位置。

this.$el.querySelector('#test_0idconese').scrollIntoView({
              behavior: 'smooth',
              inline: 'nearest',
            })

8.锚点完整代码: 

  pickUp (num) {
          if (this.pickNum > 0) {
            this.pickNum = this.pickNum - 1
            this.detailLi.content = this.detailLi.content.replace(`<span id="test_${this.pickNum}idconese" style="background-color: #00a4ff">`, `<span id="test_${this.pickNum}idconese" style="background-color: red">`)
            this.detailLi.content = this.detailLi.content.replace(`<span id="test_${(this.pickNum + 1)}idconese" style="background-color: red">`, `<span id="test_${(this.pickNum + 1)}idconese" style="background-color: #00a4ff">`)
            this.$el.querySelector(`#test_${this.pickNum}idconese`).scrollIntoView({
              behavior: 'smooth',
              inline: 'nearest',
            })
          } else if (this.pickNum === 0) {
            this.$el.querySelector('#test_0idconese').scrollIntoView({
              behavior: 'smooth',
              inline: 'nearest',
            })
          }
        },
        pickDown (num) {
          if (this.pickNum < this.allData.length - 1) {
            this.pickNum = this.pickNum + 1
            this.detailLi.content = this.detailLi.content.replace(`<span id="test_${this.pickNum}idconese" style="background-color: #00a4ff">`, `<span id="test_${this.pickNum}idconese" style="background-color: red">`)
            this.detailLi.content = this.detailLi.content.replace(`<span id="test_${(this.pickNum - 1)}idconese" style="background-color: red">`, `<span id="test_${(this.pickNum - 1)}idconese" style="background-color: #00a4ff">`)
            this.$el.querySelector(`#test_${this.pickNum}idconese`).scrollIntoView({
              behavior: 'smooth',
              inline: 'nearest',
            })
          } else if (this.pickNum === 0) {
            this.$el.querySelector('#test_0idconese').scrollIntoView({
              behavior: 'smooth',
              inline: 'nearest',
            })
          }
        },

方法2:使用文本替换锚点后。使用range方法实现切换高亮。(防止数据太多。导致上下切换高亮卡顿)

1.替换&#不可见生成的字符(例如&#130243;等之类的)并替换掉标签。使所有关键词高亮。

  test (val, x, keyWord) {
          const that = this
            this.pickNum = 0
            if (val !== '') {
              if (this.searData !== '') {
                this.detailLi.content = this.searData
              } else {
                this.searData = this.detailLi.content
              }
              const reg = new RegExp(val, 'g')
              // 正则校验先乱码过滤(&#36830;&#25509;&#25968;&#25454;&#24211;&#25104;&#21151;&#65281;)正则校验除了这种的之外
              this.detailLi.content = this.detailLi.content.replace(new RegExp('(?=\>).+?(?=\<)', 'g'), function (dades) {
                if (dades.indexOf('&#') !== -1) {
                  return dades.replace(new RegExp('((?=\&).+?)(?=\;)+\;', 'g'), function (s) {
                    const tihuan = that.decoders(s)
                    return dades.replace(dades, `${tihuan}`)
                  })
                } else {
                  return dades
                }
              })
              // 正则校验除了标签之外
              this.detailLi.content = this.detailLi.content.replace(new RegExp('(?=\>).+?(?=\<)', 'g'), function (str) {
                const reg1 = new RegExp('(?=>).+', 'g')
                return str.replace(new RegExp('(>).+', 'g'), function (str2) {
                  return str2.replace(reg1, function (str1) {
                    return str1.replace(reg, `<span id="test_idconese" style="background-color: #00a4ff">${val}</span>`)
                  })
                })
              })
              const value2 = new RegExp('test_idconese', 'gi')
              this.allData = this.detailLi.content.match(value2)
              if (this.allData && this.allData.length > 0) {
                this.allData.forEach((item, index) => {
                  this.detailLi.content = this.detailLi.content.replace('test_idconese', `test_${index}idconese`)
                })
              }
                //dom生成完毕后在执行的函数
              this.$nextTick(function () {
                if (this.$el.querySelector('#test_0idconese')) {
                  this.$el.querySelector('#test_0idconese').scrollIntoView({
                    behavior: 'smooth',
                    inline: 'nearest',
                  })
                }
                //高亮的方法
                this.upGaGaLiang(val)
              })
            } else {
              this.allData = []
            }
            //判断是否点击了关闭
            if (x) {
              if (this.searData !== '') {
                this.detailLi.content = this.searData
              } else {
                this.searData = this.detailLi.content
              }
            }
        },

2.高亮的方法函数(默认第一个高亮):

 // 高亮
        upGaGaLiang (val) {
          this.range = document.createRange()
          const container = document.getElementById('htmlcontent')
          const allText = container?.innerText
          this.inputValue = val
          if (allText && allText.includes(this.inputValue)) {
            // 获取所有节点
            const containerAllNode = container.childNodes
            // 用于保存找到的节点
            this.findNode = []
            for (let i = 0; i < containerAllNode.length; i++) {
              // 遍历查询节点
              if (containerAllNode[i].textContent?.includes(this.inputValue)) {
                this.findNode.push(containerAllNode[i])
              }
            }
            // 默认选中第一个
            if (this.findNode && this.findNode.length > 0) {
              const startNode = document.getElementById('test_0idconese').firstChild
              if (startNode) {
                this.range.setStart(startNode, 0)
                this.range.setEnd(startNode, this.ritKeyWord.length)
                const selection = window.getSelection()
                selection?.removeAllRanges()
                selection?.addRange(this.range)
              }
              // this.setSelect(0)
            }
          } else {
          }
        },

  3.切换上一个和下一个(不卡顿)

 pickUp (num) {
          if (this.pickNum > 0) {
            this.pickNum = this.pickNum - 1
            if (document.getElementById((`test_${this.pickNum}idconese`))) {
              const startNode = document.getElementById(`test_${this.pickNum}idconese`).firstChild
              if (startNode) {
                this.range.setStart(startNode, 0)
                this.range.setEnd(startNode, this.ritKeyWord.length)
                const selection = window.getSelection()
                selection?.removeAllRanges()
                selection?.addRange(this.range)
              }
              this.$el.querySelector(`#test_${this.pickNum}idconese`).scrollIntoView({
                behavior: 'smooth',
                inline: 'nearest',
              })
            }
          } else if (this.pickNum === 0) {
            if (document.getElementById('test_0idconese')) {
              const startNode = document.getElementById('test_0idconese').firstChild
              if (startNode) {
                this.range.setStart(startNode, 0)
                this.range.setEnd(startNode, this.ritKeyWord.length)
                const selection = window.getSelection()
                selection?.removeAllRanges()
                selection?.addRange(this.range)
              }
              this.$el.querySelector('#test_0idconese').scrollIntoView({
                behavior: 'smooth',
                inline: 'nearest',
              })
            }
          }
        },
        pickDown (num) {
          if (this.pickNum < this.allData.length - 1) {
            this.pickNum = this.pickNum + 1
            if (document.getElementById(`test_${this.pickNum}idconese`)) {
              const startNode = document.getElementById(`test_${this.pickNum}idconese`).firstChild
              if (startNode) {
                this.range.setStart(startNode, 0)
                this.range.setEnd(startNode, this.ritKeyWord.length)
                const selection = window.getSelection()
                selection?.removeAllRanges()
                selection?.addRange(this.range)
              }
              this.$el.querySelector(`#test_${this.pickNum}idconese`).scrollIntoView({
                behavior: 'smooth',
                inline: 'nearest',
              })
            }
          } else {
            if (this.allData.length && this.allData.length > 0) {
              if (document.getElementById(`test_${(this.allData.length - 1)}idconese`)) {
                const startNode = document.getElementById(`test_${(this.allData.length - 1)}idconese`).firstChild
                if (startNode) {
                  this.range.setStart(startNode, 0)
                  this.range.setEnd(startNode, this.ritKeyWord.length)
                  const selection = window.getSelection()
                  selection?.removeAllRanges()
                  selection?.addRange(this.range)
                }
              }
            }
          }
        },

 文章内容大致为:通过v-html渲染的页面。

  <div ref="htmlcontent" class="htmlcontent" id="htmlcontent" v-html="detailLi.content" />

data中的某些值:

data(){
    return{
          inputValue: '',
          findNode: [],
          index: -1,
          range: null,
          ritKeyWord:'',//搜索的关键词
}
}

关于方法2的知识点参考:http://t.csdn.cn/DT92m

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值