为 Jekyll 站点添加搜索功能

随着文章越写越多,页数也随之增加,可是想找到一篇文章的难度有了很大的提升。

本篇介绍我自己做的搜索功能,通过js实现。

你也可以打开dev tools查看本页面的js代码。source map已开。

搜索框

首先添加搜索框,我的实现是在navbar添加一个搜索链接,点击会滑出搜索页面,设计功力有限,页面特别丑 T_T

那么余下的是事件的绑定,略去不说,有兴趣的看一下我的事件绑定

原理

原理很简单,通过在页面上添加js代码,jekyll吐出所有文章数据,形成一个数据源,然后通过input事件触发搜索,遍历对象。然后渲染即可。

数据源

我是写在了footer.html中。每个页面都会引用此模块,所以搜索功能在所有页面中都可以调用。

点击这里查看

搜索渲染

核心代码是search.js,打开dev tools看看。

function handleSearcher() {
new Promise((resolve, reject) => {
let searchVal = searchText.value.toLowerCase().trim()
let res = posts.filter((item) => {
return (item.title.toLowerCase().indexOf(searchVal) > 0) || (item.url.toLowerCase().indexOf(searchVal) > 0)
})
resolve(res)
})
.then(res => {
// contact the dom string
let domStr = ''
for (let post of res ) {
domStr += `
<li>
<a href="
${post.url}">
<span class="title">
${post.title}</span>
<span class="url">
${post.url}</span>
</a>
</li>
`

}
return domStr
})
.then(domStr => {
// render it!
resultDom.innerHTML = domStr
})
}

其实很简单,通过Promise分成了三块。

搜索

let searchVal = searchText.value.toLowerCase().trim()
let res = posts.filter((item) => {
return (item.title.toLowerCase().indexOf(searchVal) > 0) || (item.url.toLowerCase().indexOf(searchVal) > 0)
})
resolve(res)

首先对输入数据处理一下,小写,去空格。

然后用filter遍历,只要存在输入关键字就进行下一步。

构造DOM

因为上一步的结果传过来的是数组,所以这里遍历,同时构造DOM树。

没有用createElement的原因在于性能。重复创建100个DOM树所消耗的资源比字符串操作可要大多了。

渲染

上一步传过来了构造好的DOM string,这一步就是渲染。我非常粗暴的在父DOM里直接resultDom.innerHTML = domStr

原因依旧在于性能。直接放进去会自动一次性解析DOM树,要比一次次appendChild快多了。

问题

你也看到了,问题在于我用了太多的ES2015特性而没有编译什么的。兼容性满打满算也就支持到chrome 48左右。

input事件触发的可能太频繁导致一些性能问题。

不过,我的博客而已,不用现代浏览器的我也不欢迎。