Tech Blog

ทำไมควรแยก 'เพิ่มลงตะกร้า' และ 'ซื้อเลย' ในเว็บ EC และวิธีการ Implement

by Tech Writer
Vue3 UX TypeScript Frontend

ในเว็บ 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 บนหน้ารายละเอียดภาพยนตร์ (“เช่าเดี๋ยวนี้” และ “ใส่ตะกร้า”):

ปุ่ม CTA รายละเอียดภาพยนตร์

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

Cart drawer

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

หน้าชำระเงิน


สรุป

“เพิ่มลงตะกร้า” และ “ซื้อเลย” รองรับ user intent ที่แตกต่างกันอย่างสิ้นเชิง ประเด็นสำคัญคือ:

  • ซื้อเลยไม่แตะตะกร้า
  • Components emit events เท่านั้น state จัดการใน parent
  • Checkout สลับ display ตาม mode

การแยกสอง function นี้อย่างถูกต้องนำไปสู่ checkout flow ที่ users ใช้งานได้สบาย

ส่งข้อความได้ตามสบาย

กรุณาส่งข้อความ หากมีคำปรึกษาด้านเทคนิค ความคิดเห็น หรือคำถาม