Ý tưởng tổng thể
Thông thường khi mở Init Live Search, người dùng sẽ thấy một hộp tìm kiếm trống hoặc được đẩy thẳng vào slash command mặc định như /recent. Nhưng nếu bạn muốn tạo một ấn tượng đầu tiên thật “đỉnh” — một màn hình khởi động mang tính gợi mở, hấp dẫn — thì đây là lúc để tuỳ biến.
Chúng ta sẽ tận dụng hook ils:modal-opened để chờ đúng khoảnh khắc người dùng mở modal, rồi thực hiện fetch dữ liệu qua các REST API như danh mục, thẻ, bài mới. Kết quả là một màn hình chào mừng năng động, hiện đại, giúp dẫn dắt người dùng đi sâu hơn vào nội dung trang.
Các REST API được sử dụng
Init Live Search đã tích hợp sẵn nhiều endpoint hữu ích mà bạn có thể gọi trực tiếp, không cần viết thêm backend:
GET /initlise/v1/taxonomies?taxonomy=category– danh sách chuyên mụcGET /initlise/v1/taxonomies?taxonomy=post_tag– các thẻ phổ biếnGET /initlise/v1/recent– các bài viết mới nhất
Toàn bộ danh sách endpoint đã được tổng hợp tại danh sách Endpoint REST API trong Init Live Search.
Mã JavaScript mẫu
window.addEventListener('ils:modal-opened', async function () {
const input = document.querySelector('#init-live-search-input');
if (!input || input.value.trim()) return;
const container = document.querySelector('.ils-results');
container.innerHTML = '<p class="ils-loading">Đang tải gợi ý...</p>';
const [categories, tags, recent] = await Promise.all([
fetch('/wp-json/initlise/v1/taxonomies?taxonomy=category').then(r => r.json()),
fetch('/wp-json/initlise/v1/taxonomies?taxonomy=post_tag').then(r => r.json()),
fetch('/wp-json/initlise/v1/recent').then(r => r.json()),
]);
container.innerHTML = `
<div class="ils-welcome">
<h3>Chủ đề phổ biến</h3>
<ul>${categories.slice(0, 6).map(c => `<li><a href="${c.url}" target="_blank">${c.name}</a></li>`).join('')}</ul>
<h3>Thẻ nổi bật</h3>
<ul>${tags.slice(0, 6).map(t => `<li><a href="${t.url}" target="_blank">#${t.name}</a></li>`).join('')}</ul>
<h3>Bài viết mới</h3>
<ul>${recent.slice(0, 5).map(p => `<li><a href="${p.url}" target="_blank">${p.title}</a></li>`).join('')}</ul>
</div>
`;
});
CSS nhẹ nhàng
.ils-welcome { padding: 1rem; line-height: 1.6; }
.ils-welcome h3 { margin-top: 1.5rem; }
.ils-welcome ul { list-style: none; padding-left: 0; display: flex; flex-wrap: wrap; gap: 0.5rem; }
.ils-welcome li { background: #f2f2f2; padding: 0.4rem 0.6rem; border-radius: 4px; }
Ví dụ nâng cao: giao diện chào mừng hoàn chỉnh với UIkit
Để giao diện trông mượt và hiện đại hơn, bạn có thể tận dụng sẵn UIkit (nếu trang đã dùng), kết hợp với localStorage để cache kết quả — tránh việc gọi lại REST API mỗi lần mở modal.
Dưới đây là ví dụ đã được tối ưu:
- Dùng
uk-buttonvàuk-border-pillđể hiển thị chuyên mục, thẻ nổi bật một cách sinh động. - Hiển thị danh sách bài viết mới bằng
uk-list+uk-list-divider. - Tự động lưu cache vào
localStoragevới prefixils-cache-*, đảm bảo bạn có thể dọn dẹp dễ dàng sau này bằng lệnh/clear.
window.addEventListener('ils:modal-opened', async function () {
const input = document.querySelector('#init-live-search-input');
if (!input || input.value.trim()) return;
const container = document.querySelector('.ils-results');
container.innerHTML = '<div class="uk-text-center uk-padding"><div uk-spinner></div></div>';
function getCache(key) {
const raw = localStorage.getItem('ils-cache-' + key);
try { return raw ? JSON.parse(raw) : null; } catch { return null; }
}
async function fetchAndCache(key, url) {
const res = await fetch(url).then(r => r.json());
localStorage.setItem('ils-cache-' + key, JSON.stringify(res));
return res;
}
const [categories, tags, recent] = await Promise.all([
getCache('categories') ?? fetchAndCache('categories', '/wp-json/initlise/v1/taxonomies?taxonomy=category'),
getCache('tags') ?? fetchAndCache('tags', '/wp-json/initlise/v1/taxonomies?taxonomy=post_tag'),
getCache('recent') ?? fetchAndCache('recent', '/wp-json/initlise/v1/recent'),
]);
container.innerHTML = `
<div class="uk-padding-small uk-container">
<h4 class="uk-heading-line uk-h5 uk-text-bold uk-text-muted uk-text-uppercase">
<span><span uk-icon="icon: folder"></span> Chủ đề phổ biến</span>
</h4>
<div class="uk-flex uk-flex-wrap uk-margin-bottom uk-grid-small" uk-grid>
${categories.slice(0, 6).map(c => `
<div>
<a href="${c.url}" target="_blank" class="uk-button uk-button-default uk-button-small uk-border-pill">${c.name}</a>
</div>
`).join('')}
</div>
<h4 class="uk-heading-line uk-h5 uk-text-bold uk-text-muted uk-text-uppercase">
<span><span uk-icon="icon: tag"></span> Thẻ nổi bật</span>
</h4>
<div class="uk-flex uk-flex-wrap uk-margin-bottom uk-grid-small" uk-grid>
${tags.slice(0, 6).map(t => `
<div>
<a href="${t.url}" target="_blank" class="uk-button uk-button-text uk-border-pill">#${t.name}</a>
</div>
`).join('')}
</div>
<h4 class="uk-heading-line uk-h5 uk-text-bold uk-text-muted uk-text-uppercase">
<span><span uk-icon="icon: file-text"></span> Bài viết mới</span>
</h4>
<ul class="uk-list uk-list-divider">
${recent.slice(0, 10).map(p => `
<li>
<a href="${p.url}" target="_blank" class="uk-link-heading">${p.title}</a>
</li>
`).join('')}
</ul>
</div>
`;
});
Gợi ý: Bạn hoàn toàn có thể mở rộng thêm phần này bằng cách thêm nút “Xem thêm”, hoặc gắn thẳng link slash command như /popular, /category wordpress… Nếu bạn dùng giao diện không phải UIkit, chỉ cần thay class tương ứng — logic hoàn toàn không đổi.
Tại sao chỉ fetch khi modal được mở?
Việc fetch dữ liệu được thực hiện ngay khi người dùng mở modal, chứ không từ đầu trang, mang lại nhiều lợi ích rõ rệt:
- Tiết kiệm tài nguyên: không phải tải ồ ạt các endpoint khi người dùng chưa cần.
- Chính xác về ngữ cảnh: chỉ khi người dùng mở tìm kiếm là lúc họ thực sự có nhu cầu.
- Hiệu suất tối ưu: giữ site nhẹ và nhanh, tránh gây tải cho server.
Đây chính là triết lý “Lazy Load on Intent” — chỉ phản hồi khi hành vi thực sự xảy ra, không đoán mò, không thừa thãi.
Mở rộng thêm
Bạn có thể dễ dàng nâng cấp màn hình chào mừng bằng cách bổ sung thêm các REST API khác:
- Gợi ý sản phẩm từ WooCommerce:
GET /initlise/v1/product - Bài viết theo ngày đăng:
GET /initlise/v1/date - Nội dung ngẫu nhiên hoặc phổ biến:
GET /initlise/v1/random,/popularnếu có định nghĩa
Tất cả đều có thể gắn link để người dùng click, hoặc tự động điền slash command tương ứng vào input — cực kỳ linh hoạt, tuỳ UI/UX bạn thiết kế.
Admin
05/06/2025 lúc 13:46
đoạn code nâng cao, cũng chính là JS mở rộng dùng cho chính blog này, bạn có thể thử mở tìm kiếm để xem demo trực tiếp nhé 👍