4.阅读器–阅读进度、目录、全文搜索功能开发
4.12. 全文搜索功能实现(搜索算法+数组降维)
该方法 中,q为输入的关键词,在全篇电子书中,查找关键词,返回关键词所在的位置。
doSearch(q){
return Promise.all(
this.currentBook.spine.spineItems.map(
section => section.load(this.currentBook.load.bind(this.currentBook))
.then(section.find.bind(section,q))
.finally(section.unload.bind(section))
)
)
.then(results => {
// return Promise.resolve([].concat.apply([],results))
console.log(results);
})
},
试一下调用该方法
if (this.currentBook) {
this.currentBook.ready.then(()=>{
this.doSearch('added').then(results=>{
console.log(results);
})
})
}
得到的是一组多维数组
因为得到的是二维数组,所以需要像 目录那样降维。
实际上这句就已经采用了降维的方法。
想要实现搜索功能,需要在我们搜索的时候,把目录列表隐藏掉,然后把搜索列表展示出来
再添加搜索列表
试一下 执行
看,成功打印出来了
4-13 全文搜索功能实现 (搜索关键字高亮+搜索结果高亮显示)
把返回的text 中的关键字 replace成 用span包裹起来,让span中的文字高亮
search(){
if (this.currentBook&&this.searchText.length>0&&this.searchText){
this.currentBook.ready.then(()=>{
this.doSearch(this.searchText)
.then((results)=>{
this.searchList = results
this.searchList.map(item=>{
item.excerpt = item.excerpt.replace(this.searchText,`<span class="content-search-text">${
this.searchText}</span>`);
return item;
})
});
})
}
},
当在输入框按下回车键的时候执行该方法
成功完成任务
接下来,要实现的是 点击对应的搜索列表项 跳转到对应的搜索结果页面,
只需要添加这个点击事件即可实现,当然,跳转后应该将菜单栏消失
所以我们把点击方法改成
displaySearch(target){
this.display(target,()=>{
this.hideMenuVisible();
})
},
还没完成,跳转到对应的页面之后,也应该将关键词高亮显示
电子书提供了一个方法
同时把上面方法改一下
displaySearch(target,highlight = false){
this.display(target,()=>{
this.hideMenuVisible();
if (highlight){
this.currentBook.rendition.annotations.highlight(target);
}
})
},
可见搜索结果高亮显示也完成了。
4-14 目录加载动画实现
效果如图
组件代码
<template>
<div class="ebook-loading">
<div class="ebook-loading-wrapper">
<div class="ebook-loading-item" v-for="(item, index) in data" :key="index">
<div class="ebook-loading-line-wrapper" v-for="(subItem, subIndex) in item" :key="subIndex">
<div class="ebook-loading-line" ref="line"></div>
<div class="ebook-loading-mask" ref="mask"></div>
</div>
</div>
<div class="ebook-loading-center"></div>
</div>
</div>
</template>
<script>
import {
px2rem } from './../../utils/utils'
export default {
data() {
return {
data: [
[{
}, {
}, {
}],
[{
}, {
}, {
}]
],
maskWidth: [
{
value: 0 },
{
value: 0 },
{
value: 0 },
{
value: 0 },
{
value: 0 },
{
value: 0 }
],
lineWidth: [
{
value: 16 },
{
value: 16 },
{
value: 16 },
{
value: 16 },
{
value: 16 },
{
value: 16 }
],
add: true,
end: false
}
},
methods: {
},
mounted() {
this.task = setInterval(() => {
this.$refs.mask.forEach((item, index) => {
const mask = this.$refs.mask[index]
const line = this.$refs.line[index]
let maskWidth = this.maskWidth[index]
let lineWidth = this.lineWidth[index]
if (index === 0) {
if (this.add && maskWidth.value < 16) {
maskWidth.value++
lineWidth.value--
} else if (!this.add && lineWidth.value < 16) {
maskWidth.value--
lineWidth.value++
}
} else {
if (this.add && maskWidth.value < 16) {
let preMaskWidth = this.maskWidth[index - 1]
if (preMaskWidth.value >= 8) {
maskWidth.value++
lineWidth.value--
}
} else if (!this.add && lineWidth.value < 16) {
let preLineWidth = this.lineWidth[index - 1]
if (preLineWidth.value >= 8) {
maskWidth.value--
lineWidth.value