Pretty Pretty Cooooool Search
功能分析
在较复杂的联想搜索中,想要实现这个功能,并让用户体验流畅,你可能需要一个响应非常快的服务端,还需要一套完善的缓存架构。
但对于个站来讲,大部分都是云主机,再加上个人能力有限,很难 hold 住这种架构及场景需求。
拿我的个站来讲,文章篇数不过百,服务器 1G1核1MB,整那么些,费力还不讨好。
一、数据源:
大部分个站中都会加上 RSS
,它实质上是一个 XML
类型的数据,使用 Javascript
我们可以将其转换为 JSON
数据格式,这样一来,我们便可以获取到用于搜索的数据源。
二、数据缓存:
RSS
通常由服务端响应一个 sitemap.xml
,因此通常是 GET
请求,那么浏览器作为客户端,自然会为我们做一次缓存,就和缓存 *.css
、*.js
等那些静态资源文件类似。
三、搜索筛选:
这部分只需要让 Javascript
动态获取 input
中的输入值,再去数据源中筛选出匹配的数据,最后动态改变用于显示搜索结果容器中的 innerHTML
即可。
四、总结:
1. 首先,客户端 GET 请求一个 sitemap.xml;
2. 接下来客户端会缓存它;
3. 使用 Javascript 将 sitemap.xml 转换为 JSON 格式;
4. 实时获取 input 值,并在 JSON 数据源中筛选匹配的数据;
5. 将匹配的数据动态渲染至 HTML 中。
Let's do it!
生成 sitemap.xml
我的个站服务端为 Django-1.11
,当然其他的 framework 也应该都有自己实现 sitemap.xml 的方法。拿我的个站举例:
1. 创建 feed.py
2. 定义 url
轻松愉快,2步搞定,访问一下我个站的 sitemap 吧:www.lovchun.com/sitemap.xml
客户端请求 sitemap.xml
这一步需要使用 XMLHttpRequest
,当然你如果使用 jQuery,也可以用 $.get()
:
var xmlhttp = new XMLHttpRequest();
var posts;
xmlhttp.open("GET", "/sitemap.xml");
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState != 4) return;
if (xmlhttp.status != 200 && xmlhttp.status != 304) { return; }
var node = (new DOMParser).parseFromString(xmlhttp.responseText, 'text/xml');
node = node.children[0];
// 在这一步将 XML 转换为 JSON
posts = getPostsFromXml(node);
}
xmlhttp.send();
XML TO JSON
我使用的是该工具函数:
实时获取 input 值
监听 onInputChange 事件,即可实时获取到输入框的值:
var searchInputEl = document.querySelector('#js-search__input');
searchInputEl.addEventListener('input', function onInputChange() {
console.log(this.value);
}
筛选并返回匹配项
我使用的是 fuse.js:fusejs.io,这个 package 作用便是根据你自定义的属性(key),来返回匹配项(obj)。