Jetpack 無限捲動載入文章設定 for 自製主題 - MIS 腳印
MIS 腳印 logo

MIS 腳印

記錄 IT 學習的軌跡

Jetpack 無限捲動載入文章設定 for 自製主題

如何讓自製主題輕鬆擁有無限捲動載入文章的功能,現在只要搭配 Jetpack 這套 WordPress 官方所推出的外掛即可實現,並說明相關設定與實際的原理。

WordPress.ORG

後台設定

須啟用 Jetpack 無限捲動 > 隨著讀者向下捲動頁面載入更多文章:

抽離文章區塊

將 PHP 產生文章區塊的 HTML 從 index.php 抽離存放至另一個 .php 檔,以本站來說就像下圖紅框處:

Jetpack 就是透過我們自行設定要讀取哪個 .php 檔 (通常是 content.php),來無限捲動載入文章區塊,抽離出的文章區塊程式如下:

<?php
if (have_posts()) :
    while (have_posts()) :
        the_post();
 
        echo '
        <article>
            <h2> . get_the_title() . </h2>
        </article>';
 
    endwhile;
endif;
?>

然後 index.php 或 archive.php 再使用 get_template_part('content', get_post_format()); 去讀取 content.php,且也必須設定文章區塊父元素的 ID (這裡設為 card-content),後續 functions.php 會用到:

<?php
get_header();
?>
 
    <div id="card-content">
            
        <?php
        get_template_part('content', get_post_format());
        ?>

    </div>
 
<?php
get_footer();
?>

程式碼

在 functions.php 新增如下程式,並將 container 的值對應 index.php 所設定的文章區塊父元素 ID 即可:

/**
 * Jetpack 無限捲動載入文章
 */

function infinite_scroll_render() {
    get_template_part('content');     // 指定模版檔案名稱,此例呼叫 content.php
}
add_theme_support('infinite-scroll', array(
    'container'	=> 'card-content',   // 所有文章區塊的父元素 HTML ID (對應 index.php 的設定)
    'render'	=> 'infinite_scroll_render',
    'wrapper'	=> false,            // true 時,在載入第二頁後的文章網址會添加 /page/2 (還有其它功效)
    'footer'	=> false             // 向下捲動時會,網頁最下方會顯示 Blog 的一個區塊,點擊可回到最上
));

加載圖示位置

在 style.css 新增下述 CSS 來調整 Jetpack ​​​​無限捲動載入文章時,讓加載圖示左右置中:

/*
 * Jetpack 無限捲動載入文章,加載圖示
 */
.infinite-loader {
    margin-left: -16px;
    position: absolute;
        bottom: -15px;
        left: center;
}

搭配 bricklayer.js 磚塊 (卡片) 排版

bricklayer.js 是一套輕量的磚塊排版,每個磚塊的高度均可不相同,而且磚塊的順序是由左 → 右、上 → 下,使用方式可參考 Quick Start · ademilter/bricklayer Wiki · GitHub

要讓 Jetpack 與 bricklayer.js 完美結合,必須運用 Jetpack 的二個要素:

  • 載入新文章所提供的 jQuery 事件 (Event)
  • 每次載入新文章都先會添加一個 span.infinite-loader 元素,須以此元素來追蹤所有載入的新文章。

程式碼如下:

(function($) {
    var bricklayer = new Bricklayer(document.querySelector('.bricklayer'));
    
    // Jetpack 每次載入新文章都會觸發該事件
    $(document.body).on('post-load', function () {
        // 取得 span.infinite-loader 元素
        var infiniteLoader = document.querySelectorAll('#sj_card-content .infinite-loader');
        // 取得第 1 篇新文章
        var card = infiniteLoader[infiniteLoader.length - 1].nextElementSibling;
        // 存放每次載入的所有原始新文章,以便後續用來刪除
        var cards = [];
        cards.push(card);

        // 一直往下取得載入的所有新文章
        do {
            bricklayer.append(card.cloneNode(true));    // 複製載入的新文章給 brickayer.js
            card.style.display = 'none';                // 先將載入的原始新文章隱藏
            card = card.nextElementSibling;             // 取得第 2、3... 篇新文章

            if (card)   cards.push(card);
        } while (card);

        // 刪除所有載入的原始新文章
        for (var i = 0, len = cards.length; i < len; i++) {
            cards[i].parentNode.removeChild(cards[i]);
        }
    } );
})(jQuery);

參考

發表迴響