ทำไมควรแยก 'เพิ่มลงตะกร้า' และ 'ซื้อเลย' ในเว็บ EC และวิธีการ Implement
ในเว็บ EC มีสอง button ที่แตกต่างกัน: “เพิ่มลงตะกร้า” และ “ซื้อเลย”
สอง button นี้รองรับพฤติกรรมการซื้อที่แตกต่างกัน การเข้าใจความแตกต่าง — และ implement ตามนั้น — เป็นพื้นฐานสำหรับการปรับปรุง conversion rate และ user experience
พฤติกรรมการซื้อสองประเภท
Users ที่เข้าเว็บ EC ไม่ได้ซื้อในแบบเดียวกันทั้งหมด บางคนคิดว่า “ฉันจะซื้ออันนี้ทีหลังพร้อมกับอย่างอื่น” ในขณะที่บางคนคิดว่า “ฉันต้องการอันนี้ตอนนี้ ทันที”
เพิ่มลงตะกร้า: สำหรับ users ที่ต้องการดู browse ต่อ เปรียบราคา หรือเพิ่มหลายรายการก่อนชำระ
ซื้อเลย: สำหรับ users ที่ตัดสินใจแล้ว ที่ต้องการลดขั้นตอนสู่การชำระ
ถ้ามีเพียง button เดียว ภาระของ users บางกลุ่มก็จะเพิ่มขึ้น
ความแตกต่างในบทบาทของ Button
| เพิ่มลงตะกร้า | ซื้อเลย | |
|---|---|---|
| พฤติกรรม | เพิ่มรายการลงตะกร้า → เปิด cart drawer | ข้ามตะกร้า → ไปยัง checkout โดยตรง |
| Cart state | สะท้อนในตะกร้า | ไม่กระทบตะกร้า |
| Target user | นักเปรียบเปรย | Users ที่ตัดสินใจแล้ว |
| UX | กด button → ยืนยันใน drawer | กระโดดไป payment อย่างรวดเร็ว |
สิ่งสำคัญที่ต้องระวังคือ “ซื้อเลย” ไม่แตะตะกร้า
หมายความว่า: การกด “ซื้อเลย” ไม่เพิ่มลงตะกร้า ไม่ล้างตะกร้า และเนื้อหาของตะกร้าก็ไม่เปลี่ยนแปลงหลัง Buy Now flow ด้วย
ตัวอย่าง Implementation ด้วย Vue 3
นี่คือตัวอย่าง implementation แบบ simplified โดยใช้ Vue 3
FilmDetailModal.vue (Product Detail Modal)
วาง button สอง button: “เพิ่มลงตะกร้า” และ “ซื้อเลย”
<template>
<div class="modal">
<h2>{{ film.title }}</h2>
<p>{{ film.description }}</p>
<div class="actions">
<button @click="addToCart">Add to Cart</button>
<button @click="buyNow">Buy Now</button>
</div>
</div>
</template>
<script setup lang="ts">
const props = defineProps<{ film: Film }>();
const emit = defineEmits<{
(e: "add-to-cart", film: Film): void;
(e: "buy-now", film: Film): void;
}>();
function addToCart() {
emit("add-to-cart", props.film);
}
function buyNow() {
emit("buy-now", props.film);
}
</script>
สิ่งสำคัญคือ component นี้ emit events เท่านั้น — ไม่ manipulate cart state โดยตรง
App.vue (Event Handling)
App.vue รับ events จาก modal และจัดการแตกต่างกัน
<script setup lang="ts">
import { useRouter } from "vue-router";
import { useCartStore } from "@/stores/cart";
const cartStore = useCartStore();
const router = useRouter();
function handleAddToCart(film: Film) {
cartStore.addItem(film);
isCartDrawerOpen.value = true; // เปิด cart drawer
}
function handleBuyNow(film: Film) {
// เก็บ Buy Now item แยกต่างหาก — ไม่แตะตะกร้า
buyNowItem.value = film;
router.push({ name: "checkout", query: { mode: "buy-now" } });
}
</script>
สำหรับ “เพิ่มลงตะกร้า” cart state จะถูก update และ drawer จะถูกเปิด สำหรับ “ซื้อเลย” ใช้ state แยกต่างหากและ navigate ไป checkout โดยตรง
CheckoutView.vue (Buy Now Mode Processing)
Checkout side ตรวจสอบ route query และสลับ display ตามนั้น
<script setup lang="ts">
import { useRoute } from "vue-router";
import { useCartStore } from "@/stores/cart";
const route = useRoute();
const cartStore = useCartStore();
const props = defineProps<{ buyNowItem?: Film }>();
// กำหนดสิ่งที่จะซื้อตาม mode
const isBuyNowMode = computed(() => route.query.mode === "buy-now");
const itemsToCheckout = computed(() => {
if (isBuyNowMode.value && props.buyNowItem) {
return [props.buyNowItem]; // เฉพาะ Buy Now item
}
return cartStore.items; // เนื้อหาตะกร้าปกติ
});
</script>
สิ่งนี้ทำให้มั่นใจว่าเนื้อหาตะกร้าไม่ได้รับผลกระทบเลยระหว่าง Buy Now flow
CartDrawer.vue
Cart drawer เป็น independent component ที่แสดงเนื้อหาตะกร้าเพียงอย่างเดียว เนื่องจาก “ซื้อเลย” ไม่แตะตะกร้า เนื้อหา drawer จึงไม่ได้รับผลกระทบ
<template>
<div class="cart-drawer" :class="{ open: isOpen }">
<h3>Cart</h3>
<ul>
<li v-for="item in cartStore.items" :key="item.id">
{{ item.title }} × {{ item.quantity }}
</li>
</ul>
<button @click="router.push('/checkout')">Proceed to Checkout</button>
</div>
</template>
Common Mistakes
Mistake 1: ซื้อเลยก็เพิ่มลงตะกร้าด้วย
ถ้า “ซื้อเลย” ก็เรียก cartStore.addItem() ด้วย ความไว้วางใจของ user จะพัง ความรู้สึกว่า “ฉันกด ซื้อเลย แต่รายการอื่นยังคงอยู่ในตะกร้า” นำไปสู่ cart abandonment
Mistake 2: ซื้อเลยล้างตะกร้า
ถ้าการกด “ซื้อเลย” ล้างตะกร้า user ที่คิดว่า “ฉันต้องการซื้ออันนี้ตอนนี้ แต่ก็ต้องการตรวจสอบรายการอื่นทีหลัง” ก็จะเสียตะกร้าที่จัดเรียงอย่างระมัดระวัง
วิธีที่ถูกคือการจัดการ Buy Now state แยกต่างหาก จากตะกร้า
Mistake 3: ให้เพียง Button เดียว
จากมุมมอง UX ถ้ามีเพียง “เพิ่มลงตะกร้า” users ที่ตัดสินใจแล้วก็ถูกบังคับให้ผ่านตะกร้า สิ่งนี้เพิ่มขั้นตอนที่ไม่จำเป็นและอาจลด conversion
ความสำคัญของการตัดสินใจเชิง UX Design
การ “แยกสอง button” นี้จริงๆ แล้วเกี่ยวข้องกับการตัดสินใจที่เกินกว่า UI design:
- State ไหนที่จะจัดการสำหรับ Buy Now items
- Buy Now state คงอยู่ข้ามการ navigate หน้าหรือไม่
- จะแสดง confirmation screen ใน Buy Now flow หรือไม่
นี่คือการตัดสินใจที่ design, state management, และ routing ทั้งหมดตัดกัน การตัดสินใจที่ทำใน implementation ของโปรเจคนี้ได้บันทึกไว้ใน UX Decision Log
หน้าจอจริง
ปุ่ม CTA บนหน้ารายละเอียดภาพยนตร์ (“เช่าเดี๋ยวนี้” และ “ใส่ตะกร้า”):

Cart drawer หลังกด “ใส่ตะกร้า”:

หน้าชำระเงินหลังกด “เช่าเดี๋ยวนี้”:

สรุป
“เพิ่มลงตะกร้า” และ “ซื้อเลย” รองรับ user intent ที่แตกต่างกันอย่างสิ้นเชิง ประเด็นสำคัญคือ:
- ซื้อเลยไม่แตะตะกร้า
- Components emit events เท่านั้น state จัดการใน parent
- Checkout สลับ display ตาม mode
การแยกสอง function นี้อย่างถูกต้องนำไปสู่ checkout flow ที่ users ใช้งานได้สบาย