1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
| <template> <div> <input type="text" v-model="searchText" placeholder="输入关键字" /> <button @click="goPrev">上一个</button> <button @click="goNext">下一个</button> <div ref="content" v-html="highlightedContent"></div> </div> </template>
<script> export default { data() { return { content: ``, searchText: '', highlightedContent: ` <div class="container"> <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quidem quas ut laboriosam temporibus fuga blanditiis, laborum alias debitis modi illum culpa amet qui similique assumenda aliquam error numquam, vel distinctio!</span> <div class="content"> <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quidem quas ut laboriosam temporibus fuga blanditiis, laborum alias debitis modi illum culpa amet qui similique assumenda aliquam error numquam, vel distinctio!</span> </div> <div class="footer" title="Lorem ipsum dolor sit amet consectetur adipisicing elit. Quidem quas ut laboriosam temporibus fuga blanditiis, laborum alias debitis modi illum culpa amet qui similique assumenda aliquam error numquam, vel distinctio!"> Lorem ipsum dolor sit amet consectetur adipisicing elit. Quidem quas ut laboriosam temporibus fuga blanditiis, laborum alias debitis modi illum culpa amet qui similique assumenda aliquam error numquam, vel distinctio! </div> </div> `, matches: [], currentMatch: -1 }; }, mounted() { this.content = this.$refs.content.innerHTML; }, methods: { goPrev() { if (this.currentMatch > 0) { this.currentMatch--; } else { this.currentMatch = this.matches.length - 1; } this.highlightMatch(); }, goNext() { if (this.currentMatch < this.matches.length - 1) { this.currentMatch++; } else { this.currentMatch = 0; } this.highlightMatch(); }, highlightMatch() { this.$refs.content.querySelectorAll('.highlighted').forEach((el) => { el.classList.remove('highlighted'); }); const match = this.matches[this.currentMatch]; const highlightedContent = this.content.substring(0, match.startPos) + '<span class="highlighted">' + match.text + '</span>' + this.content.substring(match.endPos); this.$refs.content.innerHTML = highlightedContent; this.$refs.content.querySelectorAll('.highlighted')[0].scrollIntoView(); }, search() { this.matches = []; this.currentMatch = -1; const regex = new RegExp(`(?![^<]*>)(${this.searchText})`, "gi"); let match; while ((match = regex.exec(this.content))) { if (!match.input.substring(match.index - 1, match.index).match(/[\w\\-]/)) { this.matches.push({ startPos: match.index, endPos: regex.lastIndex, text: match[0] }); } } if (this.matches.length > 0) { this.currentMatch = 0; this.highlightMatch(); } else { this.$refs.content.innerHTML = this.content; } } }, watch: { searchText() { this.highlightedContent = this.content; if (this.searchText) { this.search(); } } } }; </script>
<style> .highlighted { background-color: yellow; } </style>
|