给个人博客网站添加文章搜索功能的关键词检索相关文章
优采云 发布时间: 2021-04-26 04:09给个人博客网站添加文章搜索功能的关键词检索相关文章
概述
我写了文章来探索如何在个人博客网站中添加文章搜索功能,您可以轻松地通过关键词搜索相关的文章,现在让我们探索另一个功能文章添加目录导航;对于较短的文章,目录的存在影响很小,但是当文章太长时,可以提供预览和跳转的目录结构的预览将变得很重要。继续下来逐步实现它;
原理样式
要实现该功能,我们必须首先考虑其原理。目录预览实际上是一条内容,收录当前页面上不同级别标题的组合,并以结构化方式显示。首先,我们可以参考一些网站的做法,例如CSDN博客文章有一个配置目录插件,以下是我的文章之一的目录的预览:
其目录插件是右侧栏上的按钮。将鼠标放在其上时,将显示一个侧栏。内容是当前文章字幕的集合。不同级别的标题对应于不同的缩进级别,单击每个标题将具有相应的页面跳转。这基本上是一种常见且熟悉的目录形式,因此我们将以此为参考来实现;
获取目录
在要生成这样的目录之前,当然必须首先获取目录的内容。如前所述,目录的内容是当前文章的所有标题的集合,并且我们知道HTML中与标题相关的标签是h1,h2,h3,h4,h5,h6,因此只需获取他们直接,例如:
// 获取所有的标签名为 h1 的元素
document.querySelectorAll('h1');
// 获取所有的标签名为 h1 - h6 的元素
document.querySelectorAll('h1, h2, h3, h4, h5, h6');
检索到的内容是一个收录所有标题节点的数组;下一个问题是考虑如何构造存储,这是易于理解和以后阅读的。所谓结构化的,就是目录本身就是一种树形结构。例如,目录收录多个第一级标题,而某些和标题可能具有多个第二级标题,甚至向下延伸到第三级标题等,类似于以下结构:
├─ 一级标题 1
│ └─ 二级标题 1
│ └─ 三级标题 1
│ └─ 四级标题
├─ 一级标题 2
│ └─ 二级标题 1
├─ 一级标题 3
│ ├─ 二级标题 1
│ ├─ 二级标题 2
│ ├─ 二级标题 3
│ │ ├─ 三级标题 1
│ │ ├─ 三级标题 2
... ...
理论方法是将获得的标题保存在树形结构中,类似于以下内容:
[{
node: 'h1Node', // 一级标题 1 对应的节点
child: [{
node: 'h2Node', // 二级标题 1
child: [{
node: 'h3Node', // 三级标题 1
child: []
}]
},
{
node: 'h2Node', // 二级标题 2
child: []
}]
},
{
node: 'h1Node', // 一级标题 2
child: [{
node: 'h2Node', // 二级标题 1
child: []
}]
},
{
node: 'h1Node', // 一级标题 3
child: []
}]
它看起来更复杂并且占用大量空间。它需要递归获取,最后需要递归输出。通常,文章目录收录少量标题,因此暂时不使用此结构。要保存,您可以更改一种简单的思维方式,即,当我们最终生成目录时,我们可以选择逐行逐步输出,即设计以下结构:
[
'h1Node', // 一级标题 1 对应的元素节点
'h2Node', // 二级标题 1 (隶属于一级标题 1)
'h3Node', // 三级标题 1 (隶属于二级标题 1)
'h2Node', // 二级标题 2 (隶属于一级标题 1)
'h1Node', // 一级标题 2
'h2Node', // 二级标题 1 (隶属于一级标题 2)
'h1Node' // 一级标题 3
]
因为我们只需要最后输出一个格式化目录列表,即一个一个地输出,所以我们只需要以这种方式存储它,从而减少了占用的空间和复杂性;
目录生成
设置最终显示效果,如顶部样本图像所示。根据先前设计的存储结构,遍历数组并逐行打印就足够了;对于不同级别的标题,可以巧妙地使用不同程度的压痕。元素节点的nodeName属性,例如,元素节点对应的nodeName为H1,h2对应于H2,依此类推,我们使用值的最后一个数字并将其乘以固定的缩进值,以便级别增加的title节点也有一个递增的缩进值,最后一个样式部分可以使用padding-left来实现缩进。 js代码的实现思路如下:
// node 为标题节点,32 是标题级别增加而多缩进的值
node.style.paddingLeft = node.nodeName.slice(-1) * 32 + 'px';
对于单击标题以跳转到文章中相应标题的位置的功能,实现相对简单,只需设置相应的锚点即可,即title元素需要设置id属性值,然后提供单击标签的href属性。也可以将其设置为此id值,例如:
一级标题
点我跳转到一级标题</a>
第三方库的特定实现
避免重新创建轮子,而将一些基本的格式化样式留给第三方库来解决,这是Materialize库,安装和参考教程转到官方网站:check;
HTML部分
具体参考代码和说明如下:
apps
</a>
format_list_bulleted
</a>
publish
</a>
目录
Title 1
Hello World!
Hello World!
Title 1
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Title 1
Title 1
Hello World!
Hello World!
Hello World!
Title 2
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Title 3
Hello World!
Title 3
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
</p>
CSS部分
样式部分因人而异,因此您可以自己设计和调整它。以下是参考:
#category li a:before { /* 添加一个折叠符号,为了好看 */
content: "∟";
position: absolute;
left: 10px;
bottom: 5px;
font-size: 12px;
}
JavaScript部分
这部分是核心。对应于上面的HTML和CSS部分,它的实现方式如下:
// 初始化第三方库的插件
M.AutoInit();
document.addEventListener('DOMContentLoaded', function () {
var elemCategory = document.querySelector('#category');
M.Sidenav.init(elemCategory, {
'edge': 'right' // right 表示在右侧栏显示,left 则表示在左边显示
});
});
var postContent = document.querySelector('#post-content');
if (postContent) { // 存在文章内容
var categories = postContent.querySelectorAll('h1, h2, h3, h4, h5, h6');
if (categories.length > 0) { // 文章存在标题
var category = document.querySelector('#category'),
categoryBtn = document.querySelector('.category-btn');
var li = document.createElement('li'),
a = document.createElement('a');
a.className = 'waves-effect';
// 存在目录则显示目录按钮和侧栏
category.classList.remove('hide');
categoryBtn.classList.remove('hide');
categories.forEach(node => {
// 每次 cloneNode 取代 createElement
// 因为克隆一个元素快于创建一个元素
var _li = li.cloneNode(false),
_a = a.cloneNode(false);
_a.innerText = node.innerText;
// 为标题设置跳转链接
_a.href = '#' + node.id;
_li.appendChild(_a);
// 为不同级别标题应用不同的缩进
_li.style.paddingLeft = node.nodeName.slice(-1) * 32 + 'px';
category.appendChild(_li);
})
}
}
效果
最后,我附上了博客网站的一些最终渲染图,欢迎单击以访问^ _ ^