Demo
Chuẩn bị
- Đã cài plugin Init View Count và có dữ liệu lượt xem thực tế.
- Theme đang sử dụng UIkit (hoặc tích hợp riêng các class như
uk-tab,uk-switcher,uk-grid). - Biết cách thêm JavaScript vào theme hoặc plugin, ví dụ qua
wp_enqueue_scripthoặc inline trong template.
1. Tạo HTML giao diện bảng xếp hạng
Bắt đầu bằng việc xây dựng giao diện HTML đơn giản, sử dụng uk-tab để tạo các tab thời gian (Tất cả, Hôm nay, Tuần này, Tháng này), và uk-switcher để chuyển nội dung tương ứng.
<div id="view-ranking" class="uk-margin">
<ul class="uk-tab" data-uk-tab>
<li class="uk-active"><a href="#" data-range="total">Tất cả</a></li>
<li><a href="#" data-range="day">Hôm nay</a></li>
<li><a href="#" data-range="week">Tuần này</a></li>
<li><a href="#" data-range="month">Tháng này</a></li>
</ul>
<ul class="uk-switcher uk-margin">
<li>
<div class="ranking-content" data-range="total" data-loaded="false">
<!-- Skeleton chỉ cho tab đầu -->
<div class="uk-grid-small uk-flex-middle uk-margin-small" uk-grid>
<div class="uk-width-auto">
<div class="uk-background-muted uk-border-rounded" style="width:60px; height:60px;"></div>
</div>
<div class="uk-width-expand">
<div class="uk-margin-small">
<div class="uk-background-muted uk-border-rounded" style="height: 16px; width: 80%;"></div>
</div>
<div class="uk-margin-small-top">
<div class="uk-background-muted uk-border-rounded" style="height: 12px; width: 60%;"></div>
</div>
</div>
</div>
<div class="uk-grid-small uk-flex-middle uk-margin-small" uk-grid>
<div class="uk-width-auto">
<div class="uk-background-muted uk-border-rounded" style="width:60px; height:60px;"></div>
</div>
<div class="uk-width-expand">
<div class="uk-margin-small">
<div class="uk-background-muted uk-border-rounded" style="height: 16px; width: 80%;"></div>
</div>
<div class="uk-margin-small-top">
<div class="uk-background-muted uk-border-rounded" style="height: 12px; width: 60%;"></div>
</div>
</div>
</div>
<div class="uk-grid-small uk-flex-middle uk-margin-small" uk-grid>
<div class="uk-width-auto">
<div class="uk-background-muted uk-border-rounded" style="width:60px; height:60px;"></div>
</div>
<div class="uk-width-expand">
<div class="uk-margin-small">
<div class="uk-background-muted uk-border-rounded" style="height: 16px; width: 80%;"></div>
</div>
<div class="uk-margin-small-top">
<div class="uk-background-muted uk-border-rounded" style="height: 12px; width: 60%;"></div>
</div>
</div>
</div>
<div class="uk-grid-small uk-flex-middle uk-margin-small" uk-grid>
<div class="uk-width-auto">
<div class="uk-background-muted uk-border-rounded" style="width:60px; height:60px;"></div>
</div>
<div class="uk-width-expand">
<div class="uk-margin-small">
<div class="uk-background-muted uk-border-rounded" style="height: 16px; width: 80%;"></div>
</div>
<div class="uk-margin-small-top">
<div class="uk-background-muted uk-border-rounded" style="height: 12px; width: 60%;"></div>
</div>
</div>
</div>
<div class="uk-grid-small uk-flex-middle uk-margin-small" uk-grid>
<div class="uk-width-auto">
<div class="uk-background-muted uk-border-rounded" style="width:60px; height:60px;"></div>
</div>
<div class="uk-width-expand">
<div class="uk-margin-small">
<div class="uk-background-muted uk-border-rounded" style="height: 16px; width: 80%;"></div>
</div>
<div class="uk-margin-small-top">
<div class="uk-background-muted uk-border-rounded" style="height: 12px; width: 60%;"></div>
</div>
</div>
</div>
</div>
</li>
<li>
<div class="ranking-content" data-range="day" data-loaded="false"></div>
</li>
<li>
<div class="ranking-content" data-range="week" data-loaded="false"></div>
</li>
<li>
<div class="ranking-content" data-range="month" data-loaded="false"></div>
</li>
</ul>
</div>
Đặc biệt, tab đầu tiên (Tất cả) sẽ có sẵn các khối skeleton loading để tránh giao diện bị nhảy khi chưa có dữ liệu.
Lưu ý: Đây chỉ là demo HTML, nếu bạn sử dụng ở trang PHP, hãy dùng vòng lặp để xuất các khối skeleton loading nhé!
2. Thêm JavaScript để gọi REST API và hiển thị dữ liệu
Tiếp theo, bạn sẽ viết JavaScript để gọi API /wp-json/initvico/v1/top, lấy dữ liệu bài viết phổ biến theo từng mốc thời gian. Mỗi tab chỉ tải dữ liệu khi người dùng nhấn vào, giúp tối ưu hiệu năng.
document.addEventListener('DOMContentLoaded', function () {
const container = document.getElementById('view-ranking');
if (!container) return;
const tabs = container.querySelectorAll('.uk-tab a');
const contents = container.querySelectorAll('.ranking-content');
const cache = {};
function renderItem(item) {
return `
<div class="uk-grid-small uk-flex-middle uk-margin-small" uk-grid>
<div class="uk-width-auto">
<a href="${item.link}">
<img src="${item.thumbnail}" alt="${item.title}" width="60" height="60" style="object-fit:cover;" class="uk-border-rounded">
</a>
</div>
<div class="uk-width-expand">
<h5 class="uk-margin-remove"><a href="${item.link}" class="uk-link-heading">${item.title}</a></h5>
<div class="uk-text-meta">${item.views.toLocaleString()} lượt xem · ${item.date}</div>
</div>
</div>
`;
}
function renderLoading() {
let skeleton = '';
for (let i = 0; i < 5; i++) {
skeleton += `
<div class="uk-grid-small uk-flex-middle uk-margin-small" uk-grid>
<div class="uk-width-auto">
<div class="uk-background-muted uk-border-rounded" style="width:60px; height:60px;"></div>
</div>
<div class="uk-width-expand">
<div class="uk-margin-small">
<div class="uk-background-muted uk-border-rounded" style="height: 16px; width: 80%;"></div>
</div>
<div class="uk-margin-small-top">
<div class="uk-background-muted uk-border-rounded" style="height: 12px; width: 60%;"></div>
</div>
</div>
</div>
`;
}
return skeleton;
}
function loadRanking(range, target) {
if (cache[range]) {
target.innerHTML = cache[range];
return;
}
target.innerHTML = renderLoading();
fetch(`/wp-json/initvico/v1/top?range=${range}&number=5`)
.then(res => res.json())
.then(data => {
if (!Array.isArray(data)) return;
const html = data.map(renderItem).join('');
cache[range] = html;
target.innerHTML = html || '<div class="uk-text-muted">Không có dữ liệu.</div>';
target.dataset.loaded = "true";
})
.catch(() => {
target.innerHTML = '<div class="uk-text-danger">Lỗi khi tải dữ liệu.</div>';
});
}
// Map data-range => content
const contentMap = {};
contents.forEach(content => {
const range = content.dataset.range;
if (range) contentMap[range] = content;
});
// Auto load tab "Tất cả"
const firstRange = container.querySelector('.uk-tab .uk-active a')?.dataset.range;
if (firstRange && contentMap[firstRange]) {
loadRanking(firstRange, contentMap[firstRange]);
}
// Load khi chuyển tab
tabs.forEach(tab => {
tab.addEventListener('click', function () {
const range = this.dataset.range;
const target = contentMap[range];
if (!target || target.dataset.loaded === "true") return;
loadRanking(range, target);
});
});
});
Đối với tab đầu tiên, script sẽ không cần render skeleton vì bạn đã chèn sẵn trong HTML. Các tab còn lại sẽ dùng function JavaScript để hiển thị loading động trước khi dữ liệu được trả về.
Lưu ý nếu không dùng UIkit
Nếu bạn đang sử dụng một CSS framework khác như Bootstrap, Tailwind hoặc tự viết CSS, hãy thay đổi các class như uk-tab, uk-switcher, uk-grid, uk-text-meta… cho phù hợp với hệ thống của bạn. Về cơ bản, chỉ cần giữ lại cấu trúc HTML, còn class có thể tùy biến để phù hợp với thiết kế của bạn.
Kết luận
Với Init View Count và một chút tùy biến JavaScript, bạn có thể tạo bảng xếp hạng bài viết mạnh mẽ, đẹp mắt và dễ mở rộng. Đây là một ví dụ thực tế về cách tận dụng REST API plugin để kết nối trực tiếp với giao diện hiện đại mà không cần gọi shortcode từ PHP.
Bình luận