109、【Ubuntu】【Hugo】搭建私人博客:搜索功能(五)

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除

背景

上篇 blog
【Ubuntu】【Hugo】搭建私人博客:搜索引擎

分析了 Fuse.js 初始化 new Fuse(data, options),以及正排索引和倒排索引(现代搜索引擎的核心原理),下面继续

搭建私人博客

OK,接下来看下一部分

这块的整体逻辑,可以实现在用户输入搜索关键词时,实时地在页面上显示匹配的搜索结果(也就是实时搜索和自动补全等功能),下面来详细看下

sInput.onkeyup = function (e) { ... }sInput 是输入框,之前在 search.html 定义的 searchInput

当用户在输入框中松开键盘按键 onkeyup 时,触发这个函数,每次按键都会执行一次搜索,实现边打字变搜索的体验

fuse 是前面已经初始化好的 Fuse.js 实例,this.value.trim() 表示获取用户当前输入的内容,并去除收尾空格,然后调用 fuse.search(...) 对数据进行模糊匹配,如果用户有自定义配置 params.fuse.Opts.limit,就限制返回结果数量,比如只显示前面 5 条搜素结果

有搜索结果时,就构建 HTML 列表,这里可以看到用 for 循环遍历搜索结果(搜索结果 results 是一个对象数组,每个对象包含 .item 原始数据项),每个结果都会生成一个 <li> 列表项,里面包含标题和指向文章的链接 permalink,搜索结果遍历完成后,将这段动态生成的 HTML 插入到 resList 元素中,resList 就是之前在 search.html 模板里的 searchResults 元素

然后设置标志位 resultsAvailable = true,表示当前有了搜索结果,然后记录第一个和最后一个结果节点,方便后续键盘导航,比如可以用上下箭头选择

另外,这里有个点

就是这里的 <a> 标签是空的,只有 hrefaria-label,但没有显示内容,一般会把标题,也就是上面的列表项 <li> 放到 <a> 里面,或者让 <header> 包含链接,否则用户可能看不到可点击的链接,必须要做特殊处理

这里的搜索结果生成后,HTML 的列表项结构大致是这样的

html 复制代码
<li class="post-entry">
  <header class="entry-header">标题</header>
  <a href="..."></a>
</li>

可以看到 <header><a> 外面,并没有包含 <a><a> 也没有包裹 <header>,它俩是独立的,而因为 <a> 是空的,链接没有承载的地方,那用户就会点击不了,因为 <a> 没有内容(没有文本或子元素),用户就看不到可点击区域,即使鼠标悬停,也看不出这是个链接,点击时只能点到 <header>,但 <header> 不是可点击元素

比如最终效果可能是这样,如果不做特殊处理的话,那 <a> 就会点击不到

这样的话会有几个潜在影响:

  • 用户体验差:用户以为能点,但点不中
  • 无障碍性差:屏幕阅读器可能读到了 aria-label,但用户完全不知道哪里能点
  • 不符合 Web 标准:链接应该有可见内容或明确交互提示

举个标准做法例子:

html 复制代码
<li>
  <a href="/post1" aria-label="文章标题">
    <header>文章标题 >></header>
  </a>
</li>

或者更简单的:

html 复制代码
<li>
  <a href="/post1">文章标题 >></a>
</li>

这样用户看到的文字直接就是可点击的,鼠标悬停会变形状(表示可点击),屏幕阅读器也能正确识别,也符合 Web 可访问性标准

OK,下面来看 Hugo PaperMod 是怎么特殊处理这部分的,F12 打开搜索界面,可以看到

<header> 区域大小是 421.33 × 57.58 像素大小,而

<a> 区域大小则是 441.33 × 77.58 像素大小,可以看到 PaperMod 主题手动将 <a> 区域的给放大了,所以用户能点击跳转过去


OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog

相关推荐
一个处女座的程序猿O(∩_∩)O2 小时前
Next.js 与 React 深度解析:为什么选择 Next.js?
开发语言·javascript·react.js
Byte不洛2 小时前
《Linux线程原理详解:进程、轻量级进程(LWP)与pthread实战》
linux·多线程
坐怀不乱杯魂2 小时前
Linux - 进程信号
linux·c++
fanruitian2 小时前
k8s pv pvc 持久化存储
java·linux·kubernetes
Trouvaille ~2 小时前
【Linux】进程信号(一):信号的快速认识与五种产生方式
linux·运维·网络·c++·操作系统·信号处理·中断
赵民勇2 小时前
使用GSocketService创建Socket服务详解
linux·服务器
霍理迪2 小时前
JS对象与函数初相识
开发语言·javascript·ecmascript
ヤ鬧鬧o.2 小时前
HTML安全密码备忘录
前端·javascript·css·html·css3
ヤ鬧鬧o.2 小时前
小巧路径转换器优化
前端·javascript·css