xStore.products
Đọc danh mục sản phẩm: danh sách có phân trang, chi tiết, biến thể, sản phẩm liên quan.
Phương thức
| Phương thức | Cú pháp | Mô tả | Từ phiên bản |
|---|---|---|---|
list |
xStore.products.list({ limit, cursor, sort, category, collection, q, ids }): Promise<CursorPaginatedResponse<ProductCard>> |
Danh sách thẻ sản phẩm, phân trang bằng con trỏ. sort nhận newest | price_asc | price_desc; KHÔNG có featured. | 2.1 |
get |
xStore.products.get(productId): Promise<ProductDetail> |
Chi tiết sản phẩm, kèm biến thể, ảnh, thương hiệu và category_ids. | 2.1 |
getBySlug |
xStore.products.getBySlug(slug): Promise<ProductDetail> |
Chi tiết sản phẩm theo slug. Slug dùng để TRA CỨU, không dùng để ghép đường dẫn — đường dẫn nằm ở trường url. | 2.1 |
related |
xStore.products.related(productId, { limit }): Promise<CursorPaginatedResponse<ProductCard>> |
Sản phẩm liên quan, cùng hình dạng thẻ với list(). | 2.1 |
variants |
xStore.products.variants(productId): Promise<CursorPaginatedResponse<ProductVariant>> |
Biến thể của sản phẩm. Tồn kho ở đây là stock_quantity, khác với available_quantity trên thẻ sản phẩm. | 2.1 |
Ví dụ đầy đủ
<script>
// Lưới sản phẩm của một danh mục, sắp theo giá tăng dần.
async function renderGrid(categoryId) {
const trang = await xStore.products.list({
category: categoryId, // id danh mục, KHÔNG phải slug
sort: 'price_asc', // newest | price_asc | price_desc
limit: 24,
});
document.getElementById('grid').innerHTML = trang.items.map((sp) => {
// url có thể null — LUÔN kiểm tra trước khi tạo liên kết.
const href = sp.url ?? '#';
const gia = xStore.utils.formatCurrency(sp.effective_price ?? sp.price ?? 0);
return `<a class="product-card" href="${href}">
<img src="${sp.cover_image_url ?? ''}" alt="${sp.title}" loading="lazy">
<span>${sp.title}</span>
<span>${gia}</span>
</a>`;
}).join('');
// Trang tiếp theo: truyền lại next_cursor, đừng tự đoán offset.
if (trang.has_more) {
document.getElementById('more').dataset.cursor = trang.next_cursor;
}
}
// Trang chi tiết: lấy theo slug rồi đọc biến thể từ chính kết quả đó.
async function renderDetail(slug) {
const sp = await xStore.products.getBySlug(slug);
console.log(sp.title, sp.variants?.length ?? 0, 'biến thể');
}
</script>
Thư viện gọi tới /api/... trên chính tên miền cửa hàng, nên không cần khai báo địa chỉ máy chủ ở bất kỳ đâu.
Xem thêm Sự kiện để giao diện tự cập nhật sau mỗi thao tác.