You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/th/7-bank-project/2-forms
Lee Stott 2daab5271b
Update Quiz Link
3 weeks ago
..
README.md Update Quiz Link 3 weeks ago
assignment.md 🌐 Update translations via Co-op Translator 4 weeks ago

README.md

สร้างแอปธนาคาร ตอนที่ 2: สร้างฟอร์มเข้าสู่ระบบและลงทะเบียน

แบบทดสอบก่อนเรียน

แบบทดสอบก่อนเรียน

บทนำ

ในแอปเว็บสมัยใหม่เกือบทุกแอป คุณสามารถสร้างบัญชีเพื่อมีพื้นที่ส่วนตัวของคุณเองได้ เนื่องจากผู้ใช้หลายคนสามารถเข้าถึงแอปเว็บได้ในเวลาเดียวกัน คุณจึงต้องมีวิธีการจัดเก็บข้อมูลส่วนตัวของผู้ใช้แต่ละคนแยกกัน และเลือกข้อมูลที่จะแสดง เราจะไม่ครอบคลุมถึงวิธีการจัดการ ตัวตนของผู้ใช้อย่างปลอดภัย เนื่องจากเป็นหัวข้อที่กว้างขวางในตัวเอง แต่เราจะทำให้แน่ใจว่าผู้ใช้แต่ละคนสามารถสร้างบัญชีธนาคารหนึ่งบัญชี (หรือมากกว่า) ในแอปของเราได้

ในส่วนนี้ เราจะใช้ฟอร์ม HTML เพื่อเพิ่มการเข้าสู่ระบบและการลงทะเบียนในแอปเว็บของเรา เราจะเรียนรู้วิธีส่งข้อมูลไปยัง API ของเซิร์ฟเวอร์ด้วยโปรแกรม และสุดท้ายคือการกำหนดกฎการตรวจสอบความถูกต้องพื้นฐานสำหรับข้อมูลที่ผู้ใช้ป้อน

ความต้องการเบื้องต้น

คุณต้องทำส่วน เทมเพลต HTML และการกำหนดเส้นทาง ของแอปเว็บให้เสร็จสมบูรณ์ก่อนสำหรับบทเรียนนี้ นอกจากนี้ คุณยังต้องติดตั้ง Node.js และ เรียกใช้ API ของเซิร์ฟเวอร์ ในเครื่องของคุณเพื่อให้สามารถส่งข้อมูลเพื่อสร้างบัญชีได้

โปรดทราบ คุณจะต้องเปิดเทอร์มินัลสองหน้าต่างพร้อมกันดังนี้:

  1. สำหรับแอปธนาคารหลักที่เราสร้างในบทเรียน เทมเพลต HTML และการกำหนดเส้นทาง
  2. สำหรับ API เซิร์ฟเวอร์ของแอปธนาคาร ที่เราเพิ่งตั้งค่าไว้ข้างต้น

คุณต้องเปิดเซิร์ฟเวอร์ทั้งสองตัวเพื่อดำเนินการตามบทเรียนที่เหลือต่อไป เซิร์ฟเวอร์เหล่านี้จะฟังอยู่บนพอร์ตที่ต่างกัน (พอร์ต 3000 และพอร์ต 5000) ดังนั้นทุกอย่างควรทำงานได้อย่างราบรื่น

คุณสามารถทดสอบว่าเซิร์ฟเวอร์ทำงานได้อย่างถูกต้องโดยรันคำสั่งนี้ในเทอร์มินัล:

curl http://localhost:5000/api
# -> should return "Bank API v1.0.0" as a result

ฟอร์มและคอนโทรล

องค์ประกอบ <form> ใช้เพื่อครอบคลุมส่วนหนึ่งของเอกสาร HTML ที่ผู้ใช้สามารถป้อนและส่งข้อมูลผ่านคอนโทรลแบบโต้ตอบได้ มีคอนโทรลส่วนติดต่อผู้ใช้ (UI) หลายประเภทที่สามารถใช้ในฟอร์มได้ โดยทั่วไปคือองค์ประกอบ <input> และ <button>

มี <input> หลายประเภท ตัวอย่างเช่น หากต้องการสร้างช่องให้ผู้ใช้ป้อนชื่อผู้ใช้ คุณสามารถใช้:

<input id="username" name="username" type="text">

แอตทริบิวต์ name จะถูกใช้เป็นชื่อพร็อพเพอร์ตี้เมื่อส่งข้อมูลฟอร์ม ส่วนแอตทริบิวต์ id ใช้เพื่อเชื่อมโยง <label> กับคอนโทรลของฟอร์ม

ลองดูรายการ <input> types และ คอนโทรลฟอร์มอื่นๆ เพื่อทำความเข้าใจเกี่ยวกับองค์ประกอบ UI พื้นฐานที่คุณสามารถใช้ในการสร้าง UI ของคุณ

โปรดทราบว่า <input> เป็น องค์ประกอบว่างเปล่า ซึ่งคุณ ไม่ควร เพิ่มแท็กปิดที่ตรงกัน อย่างไรก็ตาม คุณสามารถใช้รูปแบบ <input/> ที่ปิดตัวเองได้ แต่ไม่จำเป็น

องค์ประกอบ <button> ภายในฟอร์มมีความพิเศษเล็กน้อย หากคุณไม่ได้ระบุแอตทริบิวต์ type มันจะส่งข้อมูลฟอร์มไปยังเซิร์ฟเวอร์โดยอัตโนมัติเมื่อกด นี่คือตัวเลือกของค่า type:

  • submit: ค่าเริ่มต้นใน <form> ปุ่มจะทำการส่งฟอร์ม
  • reset: ปุ่มจะรีเซ็ตค่าของคอนโทรลฟอร์มทั้งหมดกลับไปยังค่าเริ่มต้น
  • button: ไม่กำหนดพฤติกรรมเริ่มต้นเมื่อกดปุ่ม คุณสามารถกำหนดการกระทำที่กำหนดเองโดยใช้ JavaScript

งาน

เริ่มต้นด้วยการเพิ่มฟอร์มในเทมเพลต login เราจะต้องมีช่อง username และปุ่ม Login

<template id="login">
  <h1>Bank App</h1>
  <section>
    <h2>Login</h2>
    <form id="loginForm">
      <label for="username">Username</label>
      <input id="username" name="user" type="text">
      <button>Login</button>
    </form>
  </section>
</template>

หากคุณสังเกตดีๆ คุณจะเห็นว่าเรายังเพิ่มองค์ประกอบ <label> ด้วย <label> ใช้เพื่อเพิ่มชื่อให้กับคอนโทรล UI เช่น ช่องชื่อผู้ใช้ของเรา การใช้ป้ายกำกับมีความสำคัญต่อการอ่านฟอร์มของคุณ และยังมีประโยชน์เพิ่มเติมดังนี้:

  • การเชื่อมโยงป้ายกำกับกับคอนโทรลฟอร์มช่วยให้ผู้ใช้ที่ใช้เทคโนโลยีช่วยเหลือ (เช่น โปรแกรมอ่านหน้าจอ) เข้าใจว่าพวกเขาควรป้อนข้อมูลอะไร
  • คุณสามารถคลิกที่ป้ายกำกับเพื่อโฟกัสไปยังช่องที่เกี่ยวข้องได้โดยตรง ทำให้ง่ายต่อการใช้งานบนอุปกรณ์ที่ใช้หน้าจอสัมผัส

การเข้าถึง บนเว็บเป็นหัวข้อที่สำคัญมากซึ่งมักถูกมองข้าม ด้วยองค์ประกอบ HTML เชิงความหมาย (semantic HTML elements) การสร้างเนื้อหาที่เข้าถึงได้ไม่ใช่เรื่องยากหากคุณใช้อย่างถูกต้อง คุณสามารถ อ่านเพิ่มเติมเกี่ยวกับการเข้าถึง เพื่อหลีกเลี่ยงข้อผิดพลาดทั่วไปและเป็นนักพัฒนาที่มีความรับผิดชอบ

ตอนนี้เราจะเพิ่มฟอร์มที่สองสำหรับการลงทะเบียนไว้ด้านล่างฟอร์มแรก:

<hr/>
<h2>Register</h2>
<form id="registerForm">
  <label for="user">Username</label>
  <input id="user" name="user" type="text">
  <label for="currency">Currency</label>
  <input id="currency" name="currency" type="text" value="$">
  <label for="description">Description</label>
  <input id="description" name="description" type="text">
  <label for="balance">Current balance</label>
  <input id="balance" name="balance" type="number" value="0">
  <button>Register</button>
</form>

โดยใช้แอตทริบิวต์ value เราสามารถกำหนดค่าเริ่มต้นสำหรับช่องป้อนข้อมูลได้ สังเกตด้วยว่าช่องป้อนข้อมูลสำหรับ balance มีประเภท number ลองดูว่ามันแตกต่างจากช่องป้อนข้อมูลอื่นๆ หรือไม่ และลองโต้ตอบกับมัน

คุณสามารถนำทางและโต้ตอบกับฟอร์มโดยใช้แป้นพิมพ์เท่านั้นได้หรือไม่? คุณจะทำอย่างไร?

การส่งข้อมูลไปยังเซิร์ฟเวอร์

ตอนนี้เรามี UI ที่ใช้งานได้ ขั้นตอนต่อไปคือการส่งข้อมูลไปยังเซิร์ฟเวอร์ ลองทดสอบอย่างรวดเร็วโดยใช้โค้ดปัจจุบัน: จะเกิดอะไรขึ้นถ้าคุณคลิกปุ่ม Login หรือ Register?

คุณสังเกตเห็นการเปลี่ยนแปลงในส่วน URL ของเบราว์เซอร์หรือไม่?

ภาพหน้าจอของการเปลี่ยนแปลง URL ในเบราว์เซอร์หลังจากคลิกปุ่ม Register

การกระทำเริ่มต้นสำหรับ <form> คือการส่งฟอร์มไปยัง URL ของเซิร์ฟเวอร์ปัจจุบันโดยใช้ วิธี GET โดยเพิ่มข้อมูลฟอร์มลงใน URL โดยตรง วิธีนี้มีข้อจำกัดบางประการ:

  • ข้อมูลที่ส่งมีขนาดจำกัด (ประมาณ 2000 ตัวอักษร)
  • ข้อมูลจะมองเห็นได้โดยตรงใน URL (ไม่เหมาะสำหรับรหัสผ่าน)
  • ไม่สามารถใช้งานกับการอัปโหลดไฟล์ได้

ดังนั้นคุณสามารถเปลี่ยนไปใช้ วิธี POST ซึ่งส่งข้อมูลฟอร์มไปยังเซิร์ฟเวอร์ในเนื้อหาของคำขอ HTTP โดยไม่มีข้อจำกัดข้างต้น

แม้ว่า POST จะเป็นวิธีที่ใช้บ่อยที่สุดในการส่งข้อมูล ใน บางสถานการณ์เฉพาะ การใช้วิธี GET อาจเหมาะสมกว่า เช่น การใช้งานช่องค้นหา

งาน

เพิ่มพร็อพเพอร์ตี้ action และ method ให้กับฟอร์มการลงทะเบียน:

<form id="registerForm" action="//localhost:5000/api/accounts" method="POST">

ลองลงทะเบียนบัญชีใหม่ด้วยชื่อของคุณ หลังจากคลิกปุ่ม Register คุณควรเห็นบางอย่างเช่นนี้:

หน้าต่างเบราว์เซอร์ที่อยู่ localhost:5000/api/accounts แสดงสตริง JSON พร้อมข้อมูลผู้ใช้

หากทุกอย่างทำงานได้ดี เซิร์ฟเวอร์ควรตอบกลับคำขอของคุณด้วยการตอบกลับ JSON ที่มีข้อมูลบัญชีที่ถูกสร้างขึ้น

ลองลงทะเบียนอีกครั้งด้วยชื่อเดียวกัน จะเกิดอะไรขึ้น?

การส่งข้อมูลโดยไม่ต้องโหลดหน้าใหม่

คุณอาจสังเกตเห็นปัญหาเล็กน้อยกับวิธีที่เราใช้: เมื่อส่งฟอร์ม เราจะออกจากแอปของเราและเบราว์เซอร์จะเปลี่ยนเส้นทางไปยัง URL ของเซิร์ฟเวอร์ เรากำลังพยายามหลีกเลี่ยงการโหลดหน้าใหม่ทั้งหมดในแอปเว็บของเรา เนื่องจากเรากำลังสร้าง แอปหน้าเดียว (SPA)

เพื่อส่งข้อมูลฟอร์มไปยังเซิร์ฟเวอร์โดยไม่บังคับให้โหลดหน้าใหม่ เราต้องใช้โค้ด JavaScript แทนที่จะใส่ URL ในพร็อพเพอร์ตี้ action ขององค์ประกอบ <form> คุณสามารถใช้โค้ด JavaScript ใดๆ ที่นำหน้าด้วยสตริง javascript: เพื่อดำเนินการที่กำหนดเอง การใช้วิธีนี้หมายความว่าคุณจะต้องดำเนินการบางอย่างที่เบราว์เซอร์เคยทำโดยอัตโนมัติ:

  • ดึงข้อมูลฟอร์ม
  • แปลงและเข้ารหัสข้อมูลฟอร์มให้อยู่ในรูปแบบที่เหมาะสม
  • สร้างคำขอ HTTP และส่งไปยังเซิร์ฟเวอร์

งาน

แทนที่ action ของฟอร์มการลงทะเบียนด้วย:

<form id="registerForm" action="javascript:register()">

เปิด app.js และเพิ่มฟังก์ชันใหม่ชื่อ register:

function register() {
  const registerForm = document.getElementById('registerForm');
  const formData = new FormData(registerForm);
  const data = Object.fromEntries(formData);
  const jsonData = JSON.stringify(data);
}

ในที่นี้ เราดึงองค์ประกอบฟอร์มโดยใช้ getElementById() และใช้ตัวช่วย FormData เพื่อดึงค่าจากคอนโทรลฟอร์มเป็นชุดของคู่คีย์/ค่า จากนั้นเราแปลงข้อมูลเป็นออบเจ็กต์ปกติด้วย Object.fromEntries() และสุดท้ายแปลงข้อมูลเป็น JSON ซึ่งเป็นรูปแบบที่ใช้กันทั่วไปสำหรับการแลกเปลี่ยนข้อมูลบนเว็บ

ข้อมูลพร้อมที่จะส่งไปยังเซิร์ฟเวอร์แล้ว สร้างฟังก์ชันใหม่ชื่อ createAccount:

async function createAccount(account) {
  try {
    const response = await fetch('//localhost:5000/api/accounts', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: account
    });
    return await response.json();
  } catch (error) {
    return { error: error.message || 'Unknown error' };
  }
}

ฟังก์ชันนี้ทำอะไร? ก่อนอื่น สังเกตคำว่า async ที่นี่ ซึ่งหมายความว่าฟังก์ชันนี้มีโค้ดที่จะทำงาน แบบอะซิงโครนัส เมื่อใช้ร่วมกับคำว่า await จะช่วยให้รอให้โค้ดอะซิงโครนัสทำงานเสร็จก่อน - เช่น รอการตอบกลับจากเซิร์ฟเวอร์ที่นี่ - ก่อนดำเนินการต่อ

นี่คือวิดีโอสั้นๆ เกี่ยวกับการใช้ async/await:

Async and Await for managing promises

🎥 คลิกที่ภาพด้านบนเพื่อดูวิดีโอเกี่ยวกับ async/await

เราใช้ API fetch() เพื่อส่งข้อมูล JSON ไปยังเซิร์ฟเวอร์ วิธีนี้รับพารามิเตอร์ 2 ตัว:

  • URL ของเซิร์ฟเวอร์ ดังนั้นเราจึงใส่ //localhost:5000/api/accounts ที่นี่
  • การตั้งค่าของคำขอ ซึ่งเรากำหนดวิธีเป็น POST และให้ body สำหรับคำขอ เนื่องจากเรากำลังส่งข้อมูล JSON ไปยังเซิร์ฟเวอร์ เราจึงต้องตั้งค่าเฮดเดอร์ Content-Type เป็น application/json เพื่อให้เซิร์ฟเวอร์ทราบวิธีการตีความเนื้อหา

เนื่องจากเซิร์ฟเวอร์จะตอบกลับคำขอด้วย JSON เราสามารถใช้ await response.json() เพื่อแปลงเนื้อหา JSON และส่งคืนออบเจ็กต์ที่ได้ โปรดทราบว่าวิธีนี้เป็นแบบอะซิงโครนัส ดังนั้นเราจึงใช้คำว่า await ที่นี่ก่อนส่งคืนเพื่อให้แน่ใจว่าข้อผิดพลาดใดๆ ระหว่างการแปลงจะถูกจับด้วย

ตอนนี้เพิ่มโค้ดบางส่วนในฟังก์ชัน register เพื่อเรียก createAccount():

const result = await createAccount(jsonData);

เนื่องจากเราใช้คำว่า await ที่นี่ เราจึงต้องเพิ่มคำว่า async ก่อนฟังก์ชัน register:

async function register() {

สุดท้าย เพิ่มล็อกบางส่วนเพื่อตรวจสอบผลลัพธ์ ฟังก์ชันสุดท้ายควรมีลักษณะดังนี้:

async function register() {
  const registerForm = document.getElementById('registerForm');
  const formData = new FormData(registerForm);
  const jsonData = JSON.stringify(Object.fromEntries(formData));
  const result = await createAccount(jsonData);

  if (result.error) {
    return console.log('An error occurred:', result.error);
  }

  console.log('Account created!', result);
}

แม้จะยาวไปหน่อย แต่เราก็ทำสำเร็จ! หากคุณเปิด เครื่องมือสำหรับนักพัฒนาในเบราว์เซอร์ และลองลงทะเบียนบัญชีใหม่ คุณจะไม่เห็นการเปลี่ยนแปลงใดๆ บนหน้าเว็บ แต่ข้อความจะปรากฏในคอนโซลเพื่อยืนยันว่าทุกอย่างทำงานได้

ภาพหน้าจอแสดงข้อความล็อกในคอนโซลของเบราว์เซอร์

คุณคิดว่าข้อมูลถูกส่งไปยังเซิร์ฟเวอร์อย่างปลอดภัยหรือไม่? จะเกิดอะไรขึ้นหากมีคนสามารถดักจับคำขอได้? คุณสามารถอ่านเกี่ยวกับ HTTPS เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับการสื่อสารข้อมูลอย่างปลอดภัย

การตรวจสอบความถูกต้องของข้อมูล

หากคุณลองลงทะเบียนบัญชีใหม่โดยไม่ตั้งค่าชื่อผู้ใช้ก่อน คุณจะเห็นว่าเซิร์ฟเวอร์ส่งคืนข้อผิดพลาดพร้อมรหัสสถานะ 400 (Bad Request)

ก่อนส่งข้อมูลไปยังเซิร์ฟเวอร์ เป็นแนวปฏิบัติที่ดีในการ ตรวจสอบความถูกต้องของข้อมูลฟอร์ม ล่วงหน้าเมื่อเป็นไปได้ เพื่อให้แน่ใจว่าคุณส่งคำขอที่ถูกต้อง คอนโทรลฟอร์ม HTML5 มีการตรวจสอบความถูกต้องในตัวโดยใช้แอตทริบิวต์ต่างๆ:

  • required: ช่องนี้ต้องถูกกรอก มิฉะนั้นฟอร์มจะไม่สามารถส่งได้
  • minlength และ maxlength: กำหนดจำนวนตัวอักษรขั้นต่ำและสูงสุดในช่องข้อความ
  • min และ max: กำหนดค่าขั้นต่ำและสูงสุดของช่องตัวเลข
  • type: กำหนดประเภทของข้อมูลที่คาดหวัง เช่น number, email, file หรือ ประเภทในตัวอื่นๆ แอตทริบิวต์นี้อาจเปลี่ยนการแสดงผลของคอนโทรลฟอร์มด้วย
  • pattern: อนุญาตให้กำหนด นิพจน์ปกติ เพื่อทดสอบว่าข้อมูลที่ป้อนถูกต้องหรือไม่

เคล็ดลับ: คุณสามารถปรับแต่งรูปลักษณ์ของตัวควบคุมฟอร์มของคุณได้ โดยขึ้นอยู่กับว่ามันถูกต้องหรือไม่ โดยใช้ :valid และ :invalid CSS pseudo-classes

งาน

มีช่องข้อมูล 2 ช่องที่จำเป็นต้องกรอกเพื่อสร้างบัญชีใหม่ที่ถูกต้อง ได้แก่ ชื่อผู้ใช้และสกุลเงิน ส่วนช่องข้อมูลอื่นๆ เป็นตัวเลือกเพิ่มเติม ปรับปรุง HTML ของฟอร์มโดยใช้ทั้งแอตทริบิวต์ required และข้อความในป้ายกำกับของช่องข้อมูลให้เป็นดังนี้:

<label for="user">Username (required)</label>
<input id="user" name="user" type="text" required>
...
<label for="currency">Currency (required)</label>
<input id="currency" name="currency" type="text" value="$" required>

แม้ว่าการทำงานของเซิร์ฟเวอร์ในตัวอย่างนี้จะไม่ได้บังคับใช้ข้อจำกัดเฉพาะเกี่ยวกับความยาวสูงสุดของช่องข้อมูล แต่การกำหนดขีดจำกัดที่เหมาะสมสำหรับการป้อนข้อความของผู้ใช้ก็ถือเป็นแนวปฏิบัติที่ดีเสมอ

เพิ่มแอตทริบิวต์ maxlength ให้กับช่องข้อความ:

<input id="user" name="user" type="text" maxlength="20" required>
...
<input id="currency" name="currency" type="text" value="$" maxlength="5" required>
...
<input id="description" name="description" type="text" maxlength="100">

ตอนนี้ หากคุณกดปุ่ม Register และมีช่องข้อมูลใดที่ไม่เป็นไปตามกฎการตรวจสอบที่เรากำหนดไว้ คุณจะเห็นข้อความแสดงข้อผิดพลาดดังนี้:

ภาพหน้าจอแสดงข้อผิดพลาดการตรวจสอบเมื่อพยายามส่งฟอร์ม

การตรวจสอบความถูกต้องแบบนี้ที่ดำเนินการ ก่อน การส่งข้อมูลไปยังเซิร์ฟเวอร์เรียกว่า การตรวจสอบฝั่งไคลเอนต์ (client-side validation) แต่โปรดทราบว่าไม่สามารถตรวจสอบทุกอย่างได้โดยไม่ส่งข้อมูล ตัวอย่างเช่น เราไม่สามารถตรวจสอบได้ว่ามีบัญชีที่ใช้ชื่อผู้ใช้นี้อยู่แล้วหรือไม่โดยไม่ส่งคำขอไปยังเซิร์ฟเวอร์ การตรวจสอบเพิ่มเติมที่ดำเนินการบนเซิร์ฟเวอร์เรียกว่า การตรวจสอบฝั่งเซิร์ฟเวอร์ (server-side validation)

โดยปกติแล้ว ทั้งสองวิธีจำเป็นต้องถูกนำมาใช้ร่วมกัน การใช้การตรวจสอบฝั่งไคลเอนต์ช่วยปรับปรุงประสบการณ์ของผู้ใช้โดยให้ข้อเสนอแนะทันที แต่การตรวจสอบฝั่งเซิร์ฟเวอร์มีความสำคัญเพื่อให้แน่ใจว่าข้อมูลผู้ใช้ที่คุณจัดการนั้นถูกต้องและปลอดภัย


🚀 ความท้าทาย

แสดงข้อความแสดงข้อผิดพลาดใน HTML หากผู้ใช้นั้นมีอยู่แล้ว

นี่คือตัวอย่างของหน้าล็อกอินสุดท้ายที่สามารถดูได้หลังจากเพิ่มการตกแต่งสไตล์:

ภาพหน้าจอของหน้าล็อกอินหลังจากเพิ่มสไตล์ CSS

แบบทดสอบหลังการบรรยาย

แบบทดสอบหลังการบรรยาย

ทบทวนและศึกษาด้วยตนเอง

นักพัฒนาได้สร้างสรรค์วิธีการสร้างฟอร์มที่หลากหลาย โดยเฉพาะในเรื่องกลยุทธ์การตรวจสอบความถูกต้อง ลองเรียนรู้เกี่ยวกับกระบวนการฟอร์มที่แตกต่างกันโดยดูผ่าน CodePen; คุณสามารถหาฟอร์มที่น่าสนใจและสร้างแรงบันดาลใจได้หรือไม่?

งานที่ได้รับมอบหมาย

ตกแต่งแอปธนาคารของคุณ


ข้อจำกัดความรับผิดชอบ:
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI Co-op Translator แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความผิดที่เกิดจากการใช้การแปลนี้