在 Shopify 的 blog
模板中,默认的分页会整页刷新。如果你想优化用户体验,可以使用 fetch
来做无刷新分页切换。本文分享一个可直接使用的示例,并解释其中的关键点。
1、需求场景
-
博客文章较多,想按页展示,每页 6 篇文章
-
点击分页按钮时,不刷新整页,只替换文章列表和分页导航
-
支持浏览器前进后退按钮
-
切换分页后,页面自动平滑滚动到文章区域
2、核心代码示例
以下是完整的示例:
{%- paginate blog.articles by 6 -%}
<div class="main-cases page-width section-{{ section.id }}-padding">
<div class="section-header">
<h2 class="head_title my_h_28 my_m_28">{{ section.settings.heading }}</h2>
<p class="head_text my_h_18 my_m_12">{{ section.settings.text }}</p>
</div>
<div class="blog-articles">
{%- for article in blog.articles -%}
<div
class="blog-articles__article article{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--slide-in{% endif %}"
{% if settings.animations_reveal_on_scroll %}
data-cascade
style="--animation-order: {{ forloop.index }};"
{% endif %}
>
{%- render 'cases-card',
article: article,
media_height: section.settings.image_height,
media_aspect_ratio: article.image.aspect_ratio,
show_image: section.settings.show_image,
show_date: section.settings.show_date,
show_author: section.settings.show_author,
show_excerpt: true
-%}
</div>
{%- endfor -%}
</div>
{%- if paginate.pages > 1 -%}
<div class="pagination-wrapper">
{%- render 'pagination', paginate: paginate -%}
</div>
{%- endif -%}
</div>
{%- endpaginate -%}
<script>
document.addEventListener('click', function (e) {
const link = e.target.closest('.pagination__item');
if (link && link.tagName === 'A') {
e.preventDefault();
const url = link.getAttribute('href');
if (url) {
fetchPage(url);
}
}
});
function fetchPage(url) {
fetch(url)
.then(response => response.text())
.then(html => {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const newArticles = doc.querySelector('.blog-articles');
const newPagination = doc.querySelector('.pagination-wrapper');
if (newArticles && newPagination) {
document.querySelector('.blog-articles').innerHTML = newArticles.innerHTML;
document.querySelector('.pagination-wrapper').innerHTML = newPagination.innerHTML;
// 更新 URL,方便后退按钮
history.pushState(null, '', url);
// 平滑滚动到文章区域
const mainCases = document.querySelector('.main-cases');
if (mainCases) {
mainCases.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
}
})
.catch(err => console.error(err));
}
// 支持浏览器前进/后退按钮
window.addEventListener('popstate', () => {
fetchPage(location.href);
});
</script>
3、关键点解释
1. Liquid paginate
标签
通过 {% paginate blog.articles by 6 %}
限制每页显示 6 篇文章。
2. 渲染分页导航
{% render 'pagination', paginate: paginate %}
使用 Shopify 的分页分块。
3. 用 JS 阻止默认跳转
通过 document.addEventListener('click', ...)
捕获分页按钮点击事件,阻止默认行为,改用 fetch
加载新页面内容。
4. 用 DOMParser
更新局部内容
从返回的 HTML 中提取 .blog-articles
和 .pagination-wrapper
,只替换这两块内容。
5. history.pushState
和 popstate
使用 history.pushState
更新地址栏,监听 popstate
来支持浏览器前进/后退操作。
6. 平滑滚动
切换分页后,调用 .scrollIntoView({ behavior: 'smooth' })
平滑滚动到文章区域顶部。
4、注意事项
-
确保
.pagination-wrapper
外层要包裹好,避免替换失败。 -
该方案适用于 Dawn 等常见 Shopify 主题。
5、小结
这个方案用原生 JS 就能实现无刷新分页,无需额外依赖复杂的前端框架。
在 Shopify 的 blog
、collections
、甚至搜索结果页都可以用类似的方式实现。