🏁 Recap
Ở phần 1 và phần 2, chúng ta đã cùng nhau tìm hiểu về Shopping Template và "thực chiến" với 2 pages: Home
và Search
.
Ở phần này, mình sẽ cùng các bạn tiếp tục xây dựng giỏ hàng và thực hiện mock payment.
Mục lục
I. Quản lý state trong Tini App
II. Xây dựng giỏ hàng
- Navigate đến giỏ hàng
- Thêm sản phầm vào giỏ hàng
- Sửa số lượng sản phẩm
- Xoá sản phầm khỏi giỏ hàng
- Thêm + xoá coupon
- Tạo payment (Mở rộng)
III. Tổng kết
I. Quản lý state trong Tini App
- Mình đã có một bài viết nói về cách tiếp cận và xử lý state trong Tini App. Bạn có thể đọc bài viết
Quản lý state trong Tini App - Cái nhìn tổng quan và cách tiếp cận
Phần 1 và Phần 2. - Ý tưởng chung ở đây chúng ta sẽ dùng
app
như một global store - nơi mà mọi page và component đều có thể truy cập tới bằng methodgetApp()
. - Kết hợp
Event Emitter
để thực hiện render khiapp
thay đổi.
📌 Xem thêm getApp()
app.js
App({
cartEvent: new EventEmitter(),
cart: {
buyer: {},
seller: {},
orderedProducts: [],
productId: '',
shippingFee: 0,
price: 0,
total: 0,
coupon: {
name: '',
discount: 0,
isValid: false,
},
},
// ...
});
II. Xây dựng giỏ hàng

Như video demo ở trên, ở Cart Page
chúng ta sẽ có các actions:
- Navigate đến giỏ hàng
- Thêm sản phầm vào giỏ hàng
- Sửa số lượng sản phẩm
- Xoá sản phẩm khỏi giỏ hàng
- Thêm + xoá coupon
- Tạo payment (Mở rộng)
Hãy cùng đi từng action nào
1. Navigate đến giỏ hàng
Để navigate đến giỏ hàng, ta sẽ sử dụng jsapi my.navigateTo()
pages/detail/index.js
navigateToCart () {
my.navigateTo({ url: `pages/cart/index` });
};
📌 Xem thêm my.navigateTo()
Tuy nhiên, để gắn sự kiện cho icon ở navigation bar, chúng ta phải khai báo trong event onCustomIconEvent
pages/detail/index.js
onCustomIconEvent(e) {
navigateToCart();
},
📌 Xem thêm onCustomIconEvent()
- Mỗi khi sử dụng
my.navigateTo()
, framework sẽ push page đó vào screen stack. - Để pop screen ra khỏi stack, ta có thể bấm vào nút back trên navigation bar hoặc sử dụng jsapi
my.navigateBack()
📌 Xem thêm my.navigateBack()
2. Thêm sản phẩm vào giỏ hàng
Khi tap vào button Add to cart
, chúng ta sẽ gọi addProduct()
từ app để add sản phầm vào giỏ hàng
pages/detail/index.js
addToCart() {
getApp().addProduct(this.data.product);
},
Ta sẽ implement addProduct()
ở app như sau:
- Tìm kiếm xem ở giỏ hàng đã có sản phẩm đó chưa.
- Nếu chưa có thì add vào và cho số lượng là 1.
- Nếu có rồi thì tăng số lượng lên 1 đơn vị.
- Tính toán lại giá bằng cách gọi
calculatePrices()
- Hàm này sẽ tính toán lại giá và emit eventCART_UPDATE
.
app.js
addProduct(product) {
const position = this.cart.orderedProducts.findIndex(
(item) => item.id === product.id,
);
if (position !== -1) this.cart.orderedProducts[position].quantity += 1;
else this.cart.orderedProducts.push({ ...product, quantity: 1 });
this.calculatePrices();
},
calculatePrices() {
const { shippingFee, coupon, orderedProducts } = this.cart;
const price = orderedProducts.reduce((acc, curr) => {
return acc + curr.price * curr.quantity;
}, 0);
const total = price > 0 ? price + shippingFee - coupon.discount : 0;
this.cart = {
...this.cart,
price,
total,
};
this.cartEvent.emit(EMITTERS.CART_UPDATE, this.cart);
},
Ở pages/cart
, ta sẽ lắng nghe event CART_UPDATE
được emit ở trên và update data cart mới từ đó render lại thông tin cart
pages/cart/index.js
async onLoad() {
this.disposableCollection.push(
app.cartEvent.on(EMITTERS.CART_UPDATE, (cart) =>
this.setData({
cart,
}),
),
);
},

3. Sửa số lượng sản phẩm
Khi tap button +
hoặc -
hoặc nhập trực tiếp số vào component stepper
, ta sẽ gọi changeQuantityProduct()
của app
📌 Xem thêm stepper
pages/detail/index.js
onChangeQuantityProduct(product, quantity) {
getApp().changeQuantityProduct(product, quantity);
},
Ta sẽ implement changeQuantityProduct()
ở app như sau:
- Tìm sản phẩm trong cart.
- Update lại số lượng theo số lượng trong param nhận được.
- Tính toán lại giá bằng cách gọi
calculatePrices()
tương tự như trên.
app.js
changeQuantityProduct(product, quantity) {
const position = this.cart.orderedProducts.findIndex(
(item) => item.id === product.id,
);
if (position !== -1) {
this.cart.orderedProducts[position].quantity = quantity;
}
this.calculatePrices();
},
4. Xoá sản phầm khỏi giỏ hàng
Khi tap vào icon close, chúng ta sẽ lưu sản phẩm được chọn lại (vì trong cart có thể sẽ có nhiều sản phẩm) và show modal xác nhận

📌 Xem thêm modal
components/order-list/index.js
confirmRemoveOrder(product) {
this.selectedProduct = product;
this.setData({
modal: {
isShow: true,
headers: ['Confirmation'],
descriptions: ['Do you want to remove this product from your cart?'],
leftButton: 'Yes',
rightButton: 'No',
},
});
},
Khi tap vào Yes
, removeProduct()
ở app sẽ được gọi và nhận vào product được chọn mà ta đã lưu lại ở trên.
onRemoveProduct(product) {
app.removeProduct(product);
},
Ta sẽ implement removeProduct()
ở app như sau:
- Tìm sản phẩm trong cart.
- Remove sản phẩm khỏi cart.
- Tính toán lại giá bằng cách gọi
calculatePrices()
tương tự như trên.
app.js
removeProduct(product) {
const position = this.cart.orderedProducts.findIndex(
(item) => item.id === product.id,
);
if (position !== -1) this.cart.orderedProducts.splice(position, 1);
this.calculatePrices();
},
5. Thêm + xoá coupon
Tương tự như trên, ta cũng implement selectCoupon()
và removeCoupon()
trong app. Sau đó calculatePrices()
cũng sẽ được gọi để tính toán lại giá thành và trigger event update UI của cart.

async selectCoupon(code) {
try {
const coupon = await getCouponFromCodeAPI(code);
this.cart.coupon = coupon;
this.calculatePrices();
} catch {}
},
removeCoupon() {
this.cart.coupon = {
name: '',
discount: 0,
isValid: false,
};
this.calculatePrices();
},
6. Tạo payment (Mở rộng)
Bạn có thể để tạo payment thông qua hệ thống payment của Tiki thông qua jsapi my.makePayment()
.
📌 Xem thêm my.makePayment()
🔚 III. Tổng kết
Một lần nữa, cảm ơn các bạn đã đọc cuối bài, qua 3 phần của blog Xây dựng Shopping Template cùng Tini App
chúng ta đã tìm hiểu cách cài đặt 3 pages lớn nhất của template là Home Page
, Search Page
, Cart Page
đồng thời biết được data flows của một ứng dụng Tini Apps.
Vì thời gian có hạn nên các ví dụ ở bài blog này có thể chưa đầy đủ vì thế mình có đính kèm link github ở đây, bạn có thể clone về và ngâm cứu sâu hơn.
Hi vọng vài viết sẽ giúp ích cho bạn trong quá trình tìm hiểu và xây dựng ứng dụng trên nền tảng Tini App 🎉