如何为blogdown网站添加类似bookdown的搜索栏?
绝对可以给你的blogdown笔记站加上类似bookdown的搜索栏!用lunr.js实现静态搜索其实没你想的那么复杂,我把具体步骤拆解开,跟着做就能搞定:
1. 生成搜索所需的页面数据源
首先得让lunr.js能获取到你所有笔记的标题、标签和内容,我们需要生成一个JSON格式的数据源文件。在blogdown的layouts/目录下新建一个search.json模板文件,粘贴以下内容:
[ {{ range $index, $page := .Site.Pages }} {{ if eq $page.Type "page" }} // 这里可以根据你的需求过滤页面,比如只收录笔记类型页面 { "url": "{{ $page.Permalink }}", "title": "{{ $page.Title }}", "tags": [{{ range $tagIndex, $tag := $page.Tags }}"{{ $tag.Name }}"{{ if ne $tagIndex (sub (len $page.Tags) 1) }}, {{ end }}"], "content": "{{ $page.Content | plainify | safeJS }}" }{{ if ne $index (sub (len .Site.Pages) 1) }}, {{ end }} {{ end }} {{ end }} ]
站点构建时,这个模板会自动在根目录生成search.json,里面包含所有符合条件的页面信息。
2. 引入lunr.js和自定义搜索脚本
找个合适的地方(比如站点的footer.html或者header.html模板片段),添加lunr.js的CDN引用和搜索逻辑脚本:
<!-- 引入lunr.js库 --> <script src="https://cdn.jsdelivr.net/npm/lunr@2.3.9/lunr.min.js"></script> <!-- 自定义搜索功能脚本 --> <script> // 加载搜索数据源 fetch('/search.json') .then(response => response.json()) .then(data => { // 初始化lunr搜索索引 const idx = lunr(function () { this.ref('url'); this.field('title', { boost: 10 }); // 标题权重设高,搜索时优先匹配标题 this.field('tags', { boost: 5 }); // 标签权重次之 this.field('content'); data.forEach(doc => { this.add(doc); }); }); // 获取搜索框和结果容器元素 const searchInput = document.getElementById('search-input'); const searchResults = document.getElementById('search-results'); // 监听搜索输入事件 searchInput.addEventListener('input', function () { const query = this.value.trim(); if (!query) { searchResults.innerHTML = ''; return; } // 执行搜索并渲染结果 const results = idx.search(query); let resultHtml = ''; results.forEach(result => { const doc = data.find(item => item.url === result.ref); resultHtml += ` <div class="search-result-item"> <h3><a href="${doc.url}">${doc.title}</a></h3> <p class="search-tags">${doc.tags.join(', ')}</p> <p class="search-excerpt">${doc.content.substring(0, 150)}...</p> </div> `; }); searchResults.innerHTML = resultHtml; }); }); </script>
3. 添加搜索界面的HTML结构
在你想放置搜索栏的位置(比如导航栏顶部、页面侧边栏)插入搜索框和结果容器的HTML:
<div class="search-box-wrapper"> <input type="text" id="search-input" placeholder="搜索你的笔记..."> <div id="search-results" class="search-results-list"></div> </div>
4. 美化搜索样式(可选)
给搜索界面加一点基础CSS,让它看起来更舒服,比如把这段代码放在你的站点样式文件里:
.search-box-wrapper { position: relative; max-width: 450px; margin: 1rem auto; } #search-input { width: 100%; padding: 0.75rem 1rem; border: 1px solid #e0e0e0; border-radius: 4px; font-size: 1rem; } .search-results-list { position: absolute; top: calc(100% + 4px); left: 0; right: 0; border: 1px solid #e0e0e0; border-top: none; border-radius: 0 0 4px 4px; background: white; box-shadow: 0 2px 8px rgba(0,0,0,0.1); z-index: 100; } .search-result-item { padding: 1rem; border-bottom: 1px solid #f0f0f0; } .search-result-item:last-child { border-bottom: none; } .search-result-item h3 { margin: 0 0 0.5rem; font-size: 1.1rem; } .search-tags { margin: 0 0 0.5rem; font-size: 0.85rem; color: #666; } .search-excerpt { margin: 0; font-size: 0.9rem; color: #333; }
5. 测试与调整
完成上面的步骤后,运行blogdown::build_site()构建站点,然后本地预览测试。如果有些页面没被收录,可以修改search.json里的过滤条件;如果搜索结果的优先级不符合预期,调整lunr初始化时的boost参数即可。
内容的提问来源于stack exchange,提问作者TJ Singh
相关产品推荐
相关产品推荐

