บทความทั้งหมด

วิวิธีแก้ ส่งเมลเข้า Junk mail ด้วย WP Mail SMTP by WPForms

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

ด้วยปลั๊กอิน WP Mail SMTP แก้ไขความสามารถในการส่งอีเมลของคุณโดยกำหนดค่า WordPress ใหม่เพื่อใช้ผู้ให้บริการ SMTP ที่เหมาะสมเมื่อส่งอีเมล

  1. โหลด WP Mail SMTP โหลดที่ https://wordpress.org/plugins/wp-mail-smtp/

    และปิดใช้งาน

  2. หลังจากกดใช้งานเรียบร้อยแล้ว ไปที่เมนู

  3. ใส่ อีเมลของคุณ

  1. ตั้งชื่อที่จะแสดงตอนส่งอีเมล

  1. คลิกเลือก Gmail

  1. ไปที่เว็บ https://console.developers.google.com/flows/enableapi?apiid=gmail&pli=1 เพื่อสร้าง Client Secret และ Client ID.

  2. Login เข้าสู่ระบบ คลิก Continue เพื่อสร้าง project

  1. คลิก Go to credentials

  2. ตั้งค่าตามนี้ เเล้วคลิก Go to credentials

  3. คลิก Set Up Consent Screen

  4. เลือก Internal เเล้วคลิก Create

  5. ตั้งชื่อ App และใส่ อีเมล

  6. ใส่ link เว็บไซต์ (ต้องไม่เป็น sub web เช่น https://example.com/xxx )

  7. ใส่ email คลิก Save and Continue

  8. ใส่ชื่อเว็บไซต์

  9. กลับไปที่เว็บไซต์ ให้. copy Authorized redirect URI มา

  10. ใส่ที่ช่อง Authorized redirect URIs แล้วคลิก Refresh

  11. คลิก Create OAuth client ID

  12. ไปที่หน้า Credentials คลิกที่ I’ll do this later

  13. คลิกแก้ไขที่ app ที่เคยสร้างเอาไว้

  14. ให้ copy ส่วน Client ID และ Client secret

  15. กลับไปที่เว็บไซต์ นำค่า Client ID และ Client secret มาใส่ที่เว็บไซต์

  16. คลิกที่ Allow plugin to send emails using your Google account.

  17. คลิกที่ Allow ถ้าไม่เกิด error ถือว่าผ่านเเล้ว

  18. ขั้นตอนต่อไปคือการเทสส่งเมล

  19. เข้าไปดูที่เมล ถ้าขึ้นแบบนี้ถือว่าเรียบร้อยเเเล้ว

จากใน Section ที่แล้ว เราได้รู้พื้นฐานต่างๆของ UX UI Design ไปแล้ว ใน Section นี้ เราจะมาเริ่มทำความเข้าใจ และเจาะลึกลงไปกับ UX Design ให้มากขึ้น


หัวข้อการเรียนรู้ UX Design

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

โดยจะเรียนรู้ทั้งหมดดังนี้

  • กระบวนการ Design Thinking
  • Empathize การเข้าอกเข้าใจผู้ใช้งาน
  • Define การกำหนด การเลือกปัญหา ที่เราควรให้ความใส่ใจ
  • Ideate การสร้างสรรค์ไอเดียและการคิดไอเดียเพื่อแก้ปัญหา
  • วิธีการสร้างต้นแบบ และทดสอบต้นแบบ เพื่อนำไปสู่การสร้างผลิตภัณฑ์หรือบริการที่แท้จริง

UX Design มีอยู่ในทุกสิ่ง

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

โดยแบ่งเป็นกรณีศึกษาได้ 2 แบบ คือ

  • การออกแบบบริการ
  • การออกแบบผลิตภัณฑ์

สรุปคือ Experience หรือประสบการณ์ มีความหลากหลาย มีความแตกต่างกัน การออกแบบประสบการณ์จึงต้องใส่ใจการรับรู้และความรู้สึกเป็นสิ่งสำคัญ


แนวคิดและกระบวนการ Design Thinking

เป็นเครื่องมือที่ได้รับความนิยมมากที่สุดในการออกแบบ UX โดย Design Thinking ถูกสร้างขึ้นโดยบริษัท IDEO เป็นกระบวนการการออกแบบผลิตภัณฑ์ ซึ่งได้รับการยอมรับจากทั่วโลก ได้รับความนิยมถึงขั้นบริษัทยักษ์ใหญ่อย่าง Google, Facebook, Apple ก็ได้นำกระบวนการนี้ไปใช้งานอย่างจริงจัง จนทำให้แนวคิดนี้แพร่หลายไปทั่วโลก

Design Thinking เป็นกระบวนการที่เน้นความเข้าอกเข้าใจผู้ใช้งานเป็นสำคัญ

ซึ่งประกอบไปด้วย 5 ขั้นตอนสำคัญ คือ

  • Empathize : ความเข้าใจผู้ใช้งาน
  • Define : การเลือกปัญหาที่เราสนใจ หรือปัญหาที่เราอยากเข้าไปแก้ไข
  • Ideate : การคิดสร้างสรรค์เพื่อแก้ปัญหา
  • Prototype : การสร้างต้นแบบ โดยไม่เน้นการสร้างผลิตภัณฑ์หรือบริการจริงๆ แต่จะเป็นการสร้างต้นแบบเพื่อใช้ทดลองก่อน
  • การทดสอบ : คือการนำต้นแบบที่เราได้ไปทดสอบ

และเมื่อจบขั้นตอนที่ 5 แล้ว ก็จะวนลูปกลับสู่ Empathize อีกครั้ง

ดังนั้นการทำ Design Thinking จะเป็นกระบวนการที่ทำซ้ำไปเรื่อยๆ และเมื่อจบการทำ Design Thinking เราจะยิ่งเข้าใจผู้ใช้งานมากยิ่งขึ้น เข้าใจถึงปัญหา และได้ไอเดียการแก้ปัญหานั้นๆมากขึ้น


Empathize การเข้าอกเข้าใจผู้ใช้งาน

เริ่มจากการตั้งสมมติฐาน ปัญหา ข้อสงสัย หรือพฤติกรรมที่คุณสนใจ ซึ่งจะเป็นการ
นำไปสู่กลุ่มเป้าหมาย

ซึ่งการทำความเข้าใจผู้ใช้งาน จะมี 4 ประเด็นหลักๆ

  • สิ่งที่ผู้ใช้คิด
  • สิ่งที่ผู้ใช้พูด
  • สิ่งที่ผู้ใช้รู้สึก
  • สิ่งที่ผู้ใช้ลงมือกระทำ

โดยจะต้องเก็บข้อมูลโดยตรง ไม่ใช่แค่ทำแบบสอบถาม หรือเสิร์ชหาตาม Google ต้องเก็บรวบรวมข้อมูลจากผู้ใช้งานโดยตรง เช่น การสังเกต การสัมภาษณ์ หรือการให้ผู้ใช้งานได้ลงมือใช้จริง


การสัมภาษณ์และวิธีการตั้งคำถาม

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

5 รูปแบบคำถามหลักๆที่จำเป็นจะต้องมี

  • Variable : เป็นคำถามที่ถามเรื่องพื้นฐานทั่วไป เช่น อายุ การศึกษา เพศ ความสนใจ เป็นคำถามพื้นฐานเพื่อยืนยันว่า ผู้ที่ให้สัมภาษณ์เป็นกลุ่มเป้าหมายของเราจริงๆ

  • Mental Model : ถามความคิด ว่าผู้ที่ให้สัมภาษณ์มีความคิดเห็นอย่างไร มีมุมมองอย่างไร เช่น คุณมีความคิดอย่างไรกับเรื่องนี้

  • Activity : ถามถึงสิ่งที่ผู้ที่ให้สัมภาษณ์ลงมือกระทำ ว่าผู้ที่ให้สัมภาษณ์กระทำอย่างไร อะไรคือสิ่งที่ผู้ที่ให้สัมภาษณ์กระทำอยู่เป็นประจำ เช่น ปกติเรียนหนังสืออย่างไร

  • Motivation : ถามเกี่ยวกับความรู้สึก ถามเกี่ยวกับเป้าหมายของผู้ที่ให้สัมภาษณ์ เช่น ความสุขในชีวิตคุณคืออะไร

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

โดยขั้นตอนการสัมภาษณ์จะเริ่มต้นด้วยคำถามพื้นฐาน(Variabl)ก่อนเสมอ จากนั้นคำถามอีก 4 รูปแบบจะเรียงอย่างไรก็ได้ แต่ต้องปรับให้เหมาะสมกับผู้ที่ให้สัมภาษณ์ และสิ่งสำคัญคือต้องถามให้ครบทั้ง 5 รูปแบบ เพื่อที่จะได้รู้ในทุกๆด้านของผู้ที่ให้สัมภาษณ์


เทคนิคการสัมภาษณ์และการบันทึก

โดยพื้นฐานจะประกอบด้วยทีมงาน 3 คน ทำหน้าที่แตกต่างกัน

  • Interview : ทำการสัมภาษณ์ ทำหน้าที่ตั้งคำถามและสื่อสารกับผู้ให้สัมภาษณ์
  • Note : ทำหน้าที่จดบันทึก ไม่ต้องคิดหรือวิเคราะห์ แค่จดทุกอย่างที่เป็นข้อเท็จจริง ที่ผู้ถูกสัมภาษณ์พูดออกมา
  • Observe : ทำหน้าที่สังเกต มองพฤติกรรมของผู้ถูกสัมภาษณ์ สังเกตการกระทำ และแยกให้ออกว่าข้อมูลไหนที่พูดออกมาแล้วเป็นเรื่องจริงหรือเป็นเท็จ

หากมีผู้ให้สัมภาษณ์แค่ 2 คน คนที่ทำหน้าที่ Note ต้องคอยสังเกตพฤติกรรมด้วย และหากมีผู้สัมภาษณ์คนเดียว ให้มุ่งเน้นไปที่การสัมภาษณ์และการจดบันทึกเป็นหลัก

  1. แรกเริ่มเราจะต้องแนะนำตัวเองและบอกถึงเป้าหมายที่จะสัมภาษณ์ก่อน เพื่อให้ผู้ถูกสัมภาษณ์ไม่เครียด และสบายใจ โดยขั้นตอนนี้จะใช้เวลาประมาณ 3 นาที

  2. ให้ผู้ถูกสัมภาษณ์แนะนำตนเอง และเริ่มถามคำถาม โดยจะเป็นคำถามพื้นฐาน(Variable) ขั้นตอนนี้จะใช้เวลาประมาณ 3 นาที

  3. เริ่มถามคำถามที่อยากถาม ประเด็นที่สนใจ เพื่อเก็บข้อมูล ขั้นตอนนี้จะใช้เวลาประมาณ 15 นาที

  4. ขั้นตอนสุดท้าย หากมีบางสิ่งที่อยากให้ผู้ถูกสัมภาษณ์ลงมือปฏิบัติให้ดู หรือมีแบบสอบถาม จะใช้เวลาประมาณ 5 นาที

ทั้ง 4 ขั้นตอนนี้ไม่ควรเกินระยะเวลา 1 ชั่วโมง

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


การสังเกต

เป็นวิธีการที่มีประสิทธิภาพมาก จากการเก็บข้อมูลของผู้ใช้ วิธีการสังเกตมี 3 แบบ

  1. มองถึงรูปลักษณ์ภายนอก : สีหน้า ท่าทาง บุคลิกภาพ เป็นต้น

  2. มองพฤติกรรม : สิ่งที่ทำเป็นประจำ สิ่งที่ทำอย่างเคยชิน สิ่งที่ทำอย่างปกติ

  3. มองการกระทำ : โฟกัส หรือให้ความสำคัญกับพฤติกรรมบางอย่างที่เราสนใจ หรือเป็นพฤติกรรมที่เราอยากแก้ไขปัญหา

นอกจากนี้การสังเกตจะมีอีก 2 วิธี คือ

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

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

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


การใช้งาน Empathy Map

คือวิธีการรวบรวม และวิเคราะห์ข้อมูล ประกอบด้วย 4 ส่วน คือ

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

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


Define

คือการกำหนดเป้าหมาย หรือปัญหาที่เราสนใจ โดยข้อมูลจากตอนแรกที่ได้มาจากการสัมภาษณ์ หรือสังเกต โดยวิธีการที่เราจะเลือกปัยหามาอยู่ 3 แบบ คือ

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

สรุปคือการ Define คือการที่เราเฟ้นหาประเด็นสำคัญที่ควรค่าแก่การแก้ไข เมื่อเราเลือกปัญหาได้แล้ว เราต้องเลือกผู้ใช้ว่า เป็นใคร และจะใช้ได้อย่างไร (Persona)


การสร้าง Persona

คือการสร้างหรือกำหนดตัวผู้ใช้ขึ้นมา โดยจะเป็นการสร้างตัวละครสมมติขึ้นมาเพื่อเป็นตัวแทนของกลุ่มเป้าหมาย

  • Name : ระบุชื่อ หรือตั้งชื่อขึ้นมา โดยเป็นชื่อสมมติ

  • Photo : ใส่รูปของผู้ใช้ หารูปโดยให้บุคลิก ลักษณะท่าทาง อยู่ในกลุ่มเป้าหมาย

  • Sentence : บอกประโยคสั้นๆที่เป็นปัญหาของผู้ใช้

  • Biography : ระบุข้อมูลพื้นฐาน เช่น อายุ เพศ ส่วนสูง การศึกษา เป็นต้น

  • Behavior : ระบุพฤติกรรมของผู้ใช้ เช่น เป็นคนนอนตื่นสาย ชอบทานอาหารไทย ชอบเที่ยวต่างประเทศเดือนละครั้ง เป็นต้น

  • Pain : ระบุความทุกข์ หรือปัญหาที่ผู้ใช้เจอ ที่เราต้องการไปแก้ไข

  • Goal&Motivation : ระบุเป้าหมายว่าคืออะไร ผู้ใช้อยากได้อะไร หรืออยากให้อะไรเกิดขึ้น และเมื่อแก้ไขปัญหาแล้วอยากให้ผลลัพธ์แบบไหนเกิดขึ้น ความคาดหวังคืออะไร

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


Ideate

ในส่วนนี้่จะเน้นไปที่เรื่องของปริมาณ ไม่ใช่คุณภาพ สิ่งที่สำคัญในการคิด Idea คือ จะต้องสนุก มีความบ้า, มีความกล้า และมีความแปลกใหม่


เทคนิคการสร้างสรรค์ไอเดีย

ก่อนเราจะเริ่มสร้างไอเดีย ควรจำไว้ว่า ต้องไม่กลัวความล้มเหลว และต้องไม่กลัวข้อจำกัด

  • เทคนิคที่ 1 คือ "การตั้งคำถาม" : ต้องตั้งคำถามให้ดี ให้แหวก แล้วเราจะได้คำตอบที่สร้างสรรค์

  • เทคนิคที่ 2 คือ "การเชื่อมประสาน" : คือการนำ 2 สิ่งที่ต่างกันมากๆ มาเชื่อมต่อกัน จะทำให้ได้สิ่งใหม่ที่สร้างสรรค์มากกว่าเดิมออกมา

  • เทคนิคที่ 3 คือ "ลองทำสิ่งแปลกใหม่" : เปลี่ยนสิ่งแวดล้อมใหม่ๆ จะช่วยสร้างไอเดียแปลกใหม่

สรุปคือ การคิดสร้างสรรค์ คือการอกจากกรอบเดิมๆ ข้อจำกัดเดิมๆ และลองฝึกฝนด้วยการตั้งคำถาม, เชื่อมประสาน และทำสิ่งที่แปลกใหม่


Step Sketch

มีทั้งหมด 4 ขั้นตอน ดังนี้

ขั้นตอนที่ 1 : รวบรวมข้อมูลที่ได้มาทั้งหมดที่มี ใช้เวลาประมาณ 20 นาที

ขั้นตอนที่ 2 : คิดไอเดียออกมาเป็นข้อๆ โดยไม่จำกัด เน้นปริมาณมากๆ และเลือกมา 1 ไอเดีย ที่ชอบที่สุด ใช้เวลาประมาณ 20 นาที

ขั้นตอนที่ 3 : นำ 1 ไอเดียที่ได้มา Sketch เพิ่มเป็น 8 ไอเดีย และเลือกมา 1 ไอเดียที่ชอบที่สุด ใช้เวลาประมาณ 8 นาที

ขั้นตอนที่ 4 : นำไอเดียที่ได้มา Sketch ตั้งชื่อว่าอะไร มีขั้นตอนการทำงานอย่างไร (เริ่มอย่างไร/ทำงานอย่างไร/จบอย่างไร)


Prototype

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


เทคนิคการสร้าง Phototype

1. Paper Prototype : เหมาะกับการทดสอบ Application หรือ Website เป็นต้นแบบที่ง่ายที่สุด โดยจะวาดลงไปบนกระดาษ

2. Desktop Prototype : เหมาะกับการออกแบบบริการ หรือพื้นที่ด้านใดด้านหนึ่ง สร้างโดยใช้ของเล่น, กระดาษ หรือดินน้ำมัน (คล้ายๆกับการสร้าง Model ของสถาปัตย์)

3. Role-Play : ใช้ตัวบุคคลมาสมมติเป็นตัวละคร ใช้เพื่อทดสอบการให้บริการ

4. Cardboard Prototype : เหมาะกับการออกแบบผลิตภัณฑ์ โดยใช้อุปกรณ์คือ กระดาษแข็งที่นำมาขึ้นรูปเป็นอุปกรณ์ต่างๆ เพื่อลองให้ผู้ใช้ ทดลองจับต้องกับผลิตภัณฑ์


การวาด Wireframe สำหรับ Paper Prototype

ซึ่ง Wireframe คือเทคนิคการร่างเส้นให้ออกมาเป็น Application หรือ Website โดยคงคอนเซ็ป "หยาบ/เร็ว/ง่าย"

เริ่มต้นการวาด Wireframe จากโจทย์หรือฟังก์ชั่นที่ต้องการทำ และต้องการทดสอบ โดยใช้ฟังก์ชั่นนั้นเป็นตัวตั้ง เริ่มต้นจากหน้าแรกก่อน ว่าโครงสร้างเป็นอย่างไร และตามด้วยปุ่มต่างๆกดแล้วไปไหน ย้ำว่าวาดคร่าวๆ


Test (การทดสอบ)

หรือคือการทดลองว่าสิ่งที่เราคิด สิ่งที่เราคาดหวัง หรือไอเดียที่เราสร้างขึ้นมานั้น ตรงและให้ผลลัพธ์ตามที่เราคิดไว้หรือไม่

"เป้าหมายของการทดสอบ : การได้ Feedback"

เมื่อได้รับ Feedback จะทำให้เราเห็นผลลัพธ์ เห็นภาพชัดเจนมากขึ้น

ดังนั้นการทดสอบจึงสำคัญที่สุด เพราะมันจะนำเราไปสู่ข้อเท็จจริง และจะทำให้เราได้เรียนรู้มากขึ้น เข้าใจมากขึ้น


รูปแบบในการ Test

มี 2 รูปแบบ โดยขึ้นอยู่กับเป้าหมาย

  • การทดสอบแบบหยาบ : ไว้ใช้ทดสอบไอเดีย แนวคิด ความเป็นไปได้ของไอเดีย เช่นการใช้ Paper Prototype

  • การทดสอบแบบละเอียด : ไว้เรียนรู้ภาพย่อยๆที่มีอยู่ เช่น รายละเอียดในการออกแบบ Font, สี, ปุ่ม หรือเมื่อผู้ใช้ใช้แล้ว จะมีพฤติกรรมอย่างไร เป้าหมายเพื่ออะไร ดูว่าผู้ใช้เข้าใจการทำงานของ App, ปุ่ม, ข้อความหรือไม่


เครื่องมือที่ต้องใช้ในการ Test

สิ่งที่ต้องเตรียม

1. สถานที่ : ถ้า Test แบบหยาบ จะใช้สถานที่แบบไหน ตรงไหนก็ได้ แต่ถ้า Test แบบละเอียด จำเป็นต้องใช้สถานที่มิดชิด และส่วนตัว เพื่อให้มีสมาธิมากขึ้น

2. ทีมงาน : ประกอบไปด้วย

  • Interview : ทำหน้าที่ทดสอบ และสัมภาษณ์
  • Observer : ทำหน้าที่สังเกตการณ์ คอยมองรายละเอียด และอารมณ์
  • Simulator : ทำหน้าที่จำลองการทดสอบ เช่นทำเสียง Effect

แต่ถ้าไม่มีทีมงาน ให้สนใจแค่ข้อ 2 และ 3 ข้อ 1 ไม่จำเป็นเพราะเราอยากดูแค่พฤติกรรมของผู้ใช้

3. สิ่งที่ใช้ในการบันทึกการทดสอบ : ประกอบไปด้วย

  • กล้อง : โฟกัสที่หน้าจอ App และใบหน้าของผู้ใช้งาน
  • การจดบันทึก : เก็บรายละเอียดที่กล้องทำไม่ได้


ขั้นตอนวิธีการ Test

ขั้นตอนที่ 1 : แนะนำตัว และบอกเป้าหมายของการทดสอบ ว่าทำไปเพื่ออะไร

ขั้นตอนที่ 2 : สร้างบรรยากาศ เพื่อให้ผู้ใช้รู้สึกไม่กดดัน รู้สึกสบายๆ และบอกผู้ใช้ว่าไม่มีผลต่อเขา เป็นการทดลองผลิตภัณฑ์ หรือบริการ

ขั้นตอนที่ 3 : ให้ผู้ใช้ ได้ลองใช้งานผลิตภัณฑ์ หรือบริการ จากนั้นลอบสังเกตพฤติกรรม และสีหน้า

ขั้นตอนที่ 4 : ตั้งโจทย์ที่ผู้ผลิตอยากรู้ และให้ผู้ใช้ลองตอบ เช่น เข้าใจหรือไม่ หรืออาจจะลองกำหมดโจทย์ให้ผู้ใช้ทำ "ถ้าหากต้องการโพสรูป ต้องทำอย่างไร?" เป็นต้น

ขั้นตอนที่ 5 : สอบถามความรู้สึก, ข้อคิดเห็น หรือ Feedback ของผู้ใช้

คำถามสำคัญคือ คุณคิดว่า App นี้ เป็น App สำหรับอะไร?


จงทำซ้ำ

ทำซ้ำลูปไปเรื่อยๆ เพื่อให้ได้ผลลัพธ์ที่ดีที่สุด และเข้าใจผู้ใช้มากขึ้น!!

วิธีสร้างปุ่ม Facebook Chat บน WordPress ด้วยปลั๊กอิน The Official Facebook Chat Plugin

Facebook Chat Plugin เป็นปลั๊กอินฟรีและใช้งานง่าย เพื่อเชื่อมต่อกับลูกค้าบนเว็บไซต์ของคุณ เพียงไม่กี่ขั้นตอนคุณก็สามารถ สร้างปุ่ม Facebook Chat บนเว็บไซต์ของคุณได้

ช่วยให้ลูกค้าสามารถส่งข้อความถึงคุณในขณะดูเว็บไซต์ และข้อความของคุณสามารถดำเนินการต่อได้ในแอป Messenger facebook อีกด้วย

  1. โหลด The Official Facebook Chat Plugin โหลดที่ https://wordpress.org/plugins/facebook-messenger-customer-chat/
    และปิดใช้งาน

  2. หลังจากกดใช้งานเรียบร้อยแล้ว ไปที่เมนู

  3. คลิกที่ Setup Chat Plugin เพื่อการตั้งค่า

  1. เลือก Fanpage facebook ที่ต้องการเชื่อมต่อ (ในส่วนนี้ต้อง Login เข้า Fanpage facebook ก่อน)

  1. คลิกที่ถัดไป

  1. เลือกภาษาที่ต้องการแสดง และ เปลี่ยนคำทักทาย ในส่วนนี้จะแสดงที่หน้าเว็บไซต์เมื่อมีคนเข้าสู่เว็บไซต์ คลิก บันทึก เเละคลิกถัดไป

  1. เลือก สีของปุ่มที่ต้องการ

  1. คลิก เรียบร้อย

jQuery เป็นหนึ่งใน JavaScript Library ที่โด่งดังมาก (เมื่อ 10 ปีที่แล้ว) เรียกว่าในยุคนั้นแทบจะทุกเว็บจะต้องมีการติดตั้ง jQuery เอาไว้อย่างแน่นอน

แต่เมื่อยุคสมัยเปลี่ยนไป เบราเซอร์ใหม่ๆ ไม่มีปัญหาการรัน JavaScript ตั้งแต่ ES6 ขึ้นไปแล้ว การใช้งาน jQuery จึงลดน้อยลงเรื่อยๆ

แต่ก็มีบางโปรเจคเหมือนกัน ที่เราต้องเข้าไปแก้โค้ดเก่าๆ ซึ่งเขียนด้วย jQuery เอาไว้ ในบทความนี้จะมาเปรียบเทียบว่าทุกวันนี้เราสามารถแปลง jQuery ให้กลายเป็น Vanilla JavaScript (JavaScript เพียวๆ แบบไม่ต้องลง lib อะไรเพิ่ม เหมือนกับการกินไอติมรสเบสิกมากๆ แบบวนิลา) ได้เลยแทบจะทุกคำสั่งที่ใช้บ่อยๆ แล้วล่ะ

ในบทความนี้ก็เลยลองเอาคำสั่ง jQuery ที่ใช้บ่อยๆ มาลองเทียบดู ว่าถ้าอยากเขียนแบบนี้โดยไม่ใช้ jQuery เราจะต้องทำยังไง

Ajax

ในยุค jQuery กำลังรุ่งเรือง การเรียกข้อมูลจาก API ด้วย HTTP Request หรือที่ในยุคนั้นนิยมเรียกว่า Ajax ถ้าเขียนด้วย JavaScript แบบธรรมดาจะยากมาก

การที่ jQuery มีฟังก์ชันสำหรับเรียกใช้ Ajax ง่ายๆ ด้วยเป็นหนึ่งในเหตุผลที่ทำให้มันได้รับความนิยม ถึงขนาดว่าบางครั้งโหลด jQuery ติดเข้าไปเพราะต้องการใช้ฟังก์ชัน ajax() แค่นั้นเลยก็มีนะ

$.ajax({
  method: 'GET',
  url: '/api/data',
  data: {
    page: 1,
  },
  dataType: 'json',
  success: function(data){
    console.log('Success:', data)
  },
  error: function(error){
    console.error('Error:', error)
  },
})

แต่ข้อเสียของ jQuery.ajax() ก็คือตอนนี้ฝั่ง vanilla มีทั้ง fetch() หรือไลบรารี่อย่าง Axios ให้ใช้งาน ซึ่งทั้งสองวิธีนี้ถูกสร้างมาด้วย JavaScript ยุคใหม่โดยใช้ Promise แล้ว ไม่เหมือนกับ jQuery ที่ยังใช้สไตล์ callback function อยู่เลย

//fetch API
fetch('/api/data', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    page: 1,
  }),
})
.then(response => response.json())
.then(data => {
  console.log('Success:', data)
})
.catch((error) => {
  console.error('Error:', error)
})

//Axios
axios.get('/api/data', {
  params: {
    pafe: 1
  }
})
.then(function (response) {
  console.log('Success:', data)
})
.catch(function (error) {
  console.error('Error:', error)
})

Query Elements

First Match Element

หา element ตัวแรก

//jQuery
$('.ele').first()
$('.ele:first')

//Vanilla
document.querySelector('.box')

All Elements

หา element ทุกตัวที่ตรงกับ selector

//jQuery
$('.ele')

//Vanilla
document.querySelectorAll('.box')

สำหรับ jQuery แล้วการหา element แค่ 1 ตัวหรือหาทั้งหมด ผลที่ได้ไม่ต่างกันนั้นคืออ็อบเจคของ jQuery แต่สำหรับวนิลาแล้ว querySelector จะให้ค่ามาเป็น Element ส่วน querySelectorAll จะให้ค่าเป็น Array of Elements นะ

Nested Element

การหา element ภายใน element อีกทีหนึ่ง

//jQuery
let container = $('#container')
container.find('.box')

//Vanilla
let container = document.querySelector('.container')
container.querySelector('.box')

Action on Elements

สำหรับการสั่ง action อะไรบางอย่างกับ element ที่ได้มา ถ้าเลือกออกมาแค่ 1 element อันนี้ไม่ยาก

//jQuery
$(".box").first().doSomething()

//Vanilla
document.querySelector(".box").doSomething()

ปัญหาจะเกิดขึ้นเมื่อเรา select all กับ element ทุกตัว ซึ่งเรื่องนี้น่าจะง่ายกว่าถ้าเราใช้ jQuery เพราะการสั่ง action ของ jQuery นั้นจะวนลูปทำให้กับ element ทุกตัวอยู่แล้ว

//jQuery
$(".box").doSomething()

//Vanilla
document.querySelectorAll(".box").forEach(box => { 
    /* doSomething */ 
})

แต่สำหรับวนิลานั้น ค่าที่ได้ออกมาเป็น Array แปลว่าถ้าเราอยากสั่งให้มันทำอะไรให้ครบทุกตัว เราจะต้องวนลูปเอาเอง

เช่นสมมุติว่าเราอยาก hide ทุกอย่างที่มีคลาส box ถ้าเป็น jQuery ก็สั่งง่ายๆ เลยคือ .hide() แต่ถ้าเป็นวนิลาก็วนลูปยาวไป แล้วก็กำหนดที่ style ให้ display=none แทน

//jQuery
$(".box").hide()

//Vanilla
document.querySelectorAll(".box").forEach(box => { 
    box.style.display = "none" 
})

DOM Traversal

การวิ่งขึ้นๆ ลงๆ ใน DOM (โครงสร้างชั้นของ HTML ที่อยู่ในรูปแบบของ Tree) อันนี้ไม่ต่างกันมากเท่าไหร่ แค่คำสั่งของ jQuery จะสั้น/เขียนกระชับกว่านิดหน่อย

//jQuery
box.next()
box.prev()
box.parent()
box.children()
box.siblings()

//Vanilla
box.nextElementSibling
box.previousElementSibling
box.parentElement
box.children
box.parentNode.children.filter(el => el !== box) 

ตัวที่วนิลาไม่มีคือ siblings() ซึ่งเป็นคำสั่งเอาไว้เลือก Element ที่อยู่เลเวลเดียวกับเราทั้งหมด (แต่ไม่รวม Element ตัวเอง) ดังนั้นเลยต้องประยุกต์นิดหน่อยโดยวิ่งขึ้นไปที่ parent แล้วเลือก child ทุกตัวที่ไม่ใช่ตัวมันเองแทน

Event Handling

การกำหนด Event Listener แทบจะไม่ต่างกันแล้ว เพราะตอนหลังวนิลาก็คำสั่ง addEventListener ให้ใช้งานแล้ว

//jQuery
ele.click(function(event){})
ele.on('click', function(event){})
ele.on('mouseenter', function(event){})
ele.on('keyup', function(event){})
ele.off('click', function(event){})

//Vanilla
ele.addEventListener('click', (e) => {})
ele.addEventListener('mouseenter', (e) => {})
ele.addEventListener('keyup', (e) => {})
ele.removeEventListener('click', (e) => {})

Delegate

การดีลีเกตคือการกำหนด Event Listener ที่ Element ชั้นนอกแทนที่จะกำหนดที่ตัวมันเองตามปกติ

เช่นหากเราต้องการสร้าง Listener ที่ทำงานเมื่อกด <li> ในโครงสร้างแบบนี้

<ul>
    <li></li>
    <li></li>
    <li></li>
</ul>

เราก็ไปกำหนดให้ Listener อยู่ที่ <ul> แทน

สาเหตุที่ต้องทำแบบนี้มักจะเกิดกับกรณีที่ <li> นั้นอาจจะโดนสร้างแบบ dynamic โดย script ส่วนอื่น ทำให้อาจจะมี li เกิดขึ้นมาใหม่ได้เรื่อยๆ การไล่สั่งให้มัน Listener ทีละครั้งๆ ไปเป็นอะไรที่จัดการยากกมา เลยไปสั่งที่ ul แทน (แล้วพอเกิด Event ก็ให้ ul ส่งไปบอก li ภายในอีกที)

สำหรับวนิลาไม่มีคำสั่งให้ทำดีลีเกตได้เหมือน jQuery ดังนั้นก็ต้องประยุกต์เอาอีกแล้ว (ฮา)

//jQuery
container.on('click', '.box', function(event){
    //...
})

//Vanilla
container.addEventListener('click', function(event){
  if(event.target.matches('.box')){
      //...
  }
})

Create Event

อันนี้เป็นการสร้าง Event ขึ้นมาเอง .. ไม่ต่างกันมากนัก

//jQuery
ele.trigger('click')

//Vanilla
ele.dispatchEvent(new Event('click'))

Styling

การเซ็ต CSS ให้กับ Element

ของ jQuery จะใช้คำสั่ง .css() แต่วนิลาสามารถเซ็ตลงไปได้ผ่าน properties ที่ชื่อว่า .style

//jQuery
ele.css('color', '#000')
ele.css({
  'color': '#000',
  'background': '#FFF',
})

//Vanilla
ele.style.color = '#000'
ele.style.background = '#FFF'
ele.style.cssText = 'color: #000, background: #FFF'

บางครั้ง jQuery ก็มีฟังก์ชันที่จริงๆ เบื้องหลักก็ไปเซ็ตค่า css นั่นแหละแบบนี้ด้วยนะ

//jQuery
box.hide()
box.show()

//Vanilla
box.style.display = 'none'
box.style.display = 'block'

Document Ready

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

สำหรับ vanilla นั้นไม่มีคำสั่งสำเร็จขนาดนั้น แต่ถ้าอยากได้ก็เขียนได้ ... แต่เอาจริงๆ ส่วนใหญ่เราจะใช้วิธีเรียกฟังก์ชันที่ท้ายๆ ของหน้าเพจมากกว่า

//jQuery
$(document).ready(function(){ 
  /*...*/ 
})

$(function(){ 
  /*...*/ 
})

//Vanilla
(function(callback){
  if (document.readyState != "loading") callback()
  else document.addEventListener("DOMContentLoaded", callback)
})(function(){
   /*...*/
})

Class Properties

สำหรับสำหรับจัดการ class ซึ่งตอนนี้ฝั่ง vanilla ก็ทำได้ทั้งหมดเหมือน jQuery แล้วผ่าน properties ชื่อ classList

//jQuery
box.addClass('active focus')
box.removeClass('active')
box.toggleClass('active')
box.hasClass('active')

//Vanilla
box.classList.add('active', 'focus')
box.classList.remove('active')
box.classList.toggle('active')
box.classList.replace('active', 'blur')
box.classList.contains('active')

Create Virtual Element

Virtual Element เป็นการสร้าง Element HTML ขึ้นมาในฝั่ง JavaScript ซึ่งสามารถเอาไปปะให้แสดงผลใน document ได้ ซึ่งหลายๆ เฟรมเวิร์คตอนนี้ก็ใช้วิธีนี้แหละ ในการควบคุมการทำงานระหว่างสคริปกับ HTML

สำหรับ jQuery การสร้าง Virtual Element แค่เติม <> ครอบชื่อแท็กลงไปก็พอแล้ว ซึ่งเราจะได้ element ออกมา สามารถเอาไปใช้งานได้เลย

ทางฝั่ง vanilla ตอนนี้วิธีสร้าง Virtual Element ก็ไม่ยากล่ะ เพราะมีคำสั่ง createElement ให้ใช้

//jQuery
let div = $('<div>')
div.text('Hello World!')
div.html('Hello World!')

//Vanilla
let div = document.createElement('div')
div.textContent = 'Hello World!'
div.innerHTML = 'Hello World!'

DOM Manipulate

การจัดการ DOM อันนี้เราคิดว่าคำสั่งทางฝั่ง vanilla อ่านเข้าใจง่ายกว่า

คือแบ่งเป็น 2 เรื่อง การแก้ไข DOM ภายใน กับ ภายนอก (replace)

//jQuery
el.replaceWith('x')
el.html('x')

//Vanilla
el.outerHTML = 'x'
el.innserHTML = 'x'

ส่วนการเพิ่ม element เข้าไป ก็มี 2 คำสั่งคือเพิ่มต่อท้าย กับเพิ่มแทรกเข้าไปเป็นตัวแรก ซึ่งฝั่ง vanilla นั้นไม่มีคำสั่งเพิ่มแบบแทรกเข้าไปเป็นตัวแรก ต้องหา child ตัวแรกให้ได้ก่อน แล้วใช้ insertBefore ต่ออีกที

//jQuery
ul.append($('<li>'))
ul.prepend($('<li>'))

//Vanilla
ul.appendChild(document.createElement('li'))
ul.insertBefore(document.createElement('li'), parent.firstChild)

เรื่องการลบทิ้ง, การแทรกในตำแหน่งต่างๆ, และการ clone อันนี้ไม่ยากเท่าไหร่

//jQuery
el.remove()

//Vanilla
el.parentNode.removeChild(el)
//jQuery
$(target).after(element)
$(target).before(element)

//Vanilla
target.insertAdjacentElement('afterend', element)
target.insertAdjacentElement('beforebegin', element)
//jQuery
$(el).clone()

//Vanilla
el.cloneNode(true)

Attribute

เรื่องการจัดการ attribute ฝั่ง jQuery จะพิเศษหน่อยตรงมี data() ให้ใช้งานด้วย

//jQuery
el.prop('data-x')
el.attr('data-x')
el.data('x')

//Vanilla
el['data-x']
//jQuery
el.removeAttr('data-x')

//Vanilla
el.removeAttribute('data-x')

Effect

สำหรับ jQuery นั้นมีฟังก์ชันที่ทำให้เราโชว์/ซ่อน element แบบมีอนิเมชันได้ด้วย เช่น fadeOut, fadeIn, slideUp, slideDown (ซึ่งเบื้องหลังเป็นการสั่งเปลี่ยนค่าพวกความสูงหรือ opacity ด้วยลูปเอานะ)

สำหรับการเขียนแบบใหม่ ตอนนี้เราไม่นิยมให้ JavaScript เป็นคนจัดการอนิเมชันแล้ว แต่โยนไปเป็นหน้าที่ของ css แทน เช่นการใช้ transition

ฝั่ง JavaScript มีหน้าที่แค่ระบุคลาสของ css เข้าไปเท่านั้นพอ

//jQuery
$(el).fadeOut()

//Vanilla
el.classList.add('hide')
el.classList.remove('show')
/* With this CSS */
.show {
  opacity: 1;
}
.hide {
  opacity: 0;
  transition: opacity 400ms;
}

จริงๆ น่าจะยังมีอีกหลายคำสั่ง

Vue 3 เพิ่งเปิดตัวมาเมื่อเดือนที่แล้ว ซึ่งมาพร้อมกับฟีเจอร์ใหม่ๆ และสิ่งที่เปลี่ยนแปลงไป เรามาดูกันดีกว่า

เขียนใหม่ด้วย TypeScript

ภาษา JavaScript นั้นไม่มี Type ของตัวแปรทำให้เวลาเขียนโปรแกรมมีโอกาสเกิดข้อผิลพลาดเยอะ ดังนั้นการเขียนงานโปรเจคใหญ่ๆ คนเลยนิยมเปลี่ยนไปใช้ TypeScript แทน (ถ้ายังไม่รู้จัก TypeScript อ่านต่อได้ที่นี่)

สำหรับ Vue 3.0 นี้ก็เป็นการเขียนใหม่ด้วย TypeScript แทน แต่เวลาเราเอามาใช้งาน เราสามารถเลือกได้ว่าจะใช้แบบ JavaScript ตามปกติ หรือจะใช้แบบ TypeScript ก็ได้

interface Book {
  title: string
  author: string
  year: number
}

const Component = defineComponent({
  data() {
    return {
      book: {
        title: 'Vue 3 Guide',
        author: 'Vue Team',
        year: 2020
      } as Book
    }
  }
})

อ่านเรื่อง TypeScript ต่อได้ที่นี่

JSX

เป็นฟีเจอร์ที่เอามาจาก React นั้นคือแทนที่จะใช้ Hyperscript แบบนี้

Vue.h(
  Vue.resolveComponent('anchored-heading'),
  {
    level: 1
  },
  [Vue.h('span', 'Hello'), ' world!']
)

Vue.h ย่อมาจาก Hyperscript ซึ่งหมายถึง script ที่เอาไว้สร้าง HTML structures นั่นเอง

การเขียน JSX ได้จะทำให้เราเขียน HTML ลงไปในโค้ด JavaScript ตรงๆ ได้เลย

import AnchoredHeading from './AnchoredHeading.vue'

const app = createApp({
  render() {
    return (
      <AnchoredHeading level={1}>
        <span>Hello</span> world!
      </AnchoredHeading>
    )
  }
})

app.mount('#demo')

อ่านเรื่อง JSX ต่อได้ที่นี่

API ที่เปลี่ยนไปใน Vue 3

ในหัวข้อนี้ขอยกตัวอย่างโค้ดข้างล่างนี่ ซึ่งรันได้ปกติใน Vue 2

<div id="app">
    <h1>{{ title }}</h1>
    <my-button @whenclick="changeTitleText"></my-button>
</div>

<script src="https://unpkg.com/[email protected]"></script>
<script>
Vue.component('my-button', {
    template: `
        <button @click="handleClick">Click Me!</button>
    `,
    methods: {
        handleClick(){
            this.$emit('whenclick')
        }
    },
})

let app = new Vue({
    el: '#app',
    data: {
        title: 'นี่คือ Title แบบ Vue 2',
    },
    methods: {
        changeTitleText(){
            this.title = 'โค้ดนี้ทำงานได้ใน Vue 2'
        }
    },
})
</script>

See the Pen
Vue3-change-1
by Ta Tanapoj Chaivanichanan (@tanapoj)
on CodePen.

ในตัวอย่างนี้มีการสร้าง component ชื่อ my-button ขึ้นมาหนึ่งตัว แล้วตั้งค่าไว้ว่าถ้ามีการคลิก ให้เปลี่ยนข้อความ title ซะ

ทีนี้ ถ้าเราเปลี่ยนไปใช้ Vue 3 ตัวนี้แทน https://unpkg.com/[email protected] เราจะพบว่าโค้ดของเรารันไม่ได้ไปซะแล้ว

สาเหตุก็เพราะว่า API การเรียกใช้งานมีการเปลี่ยนแปลง

วิธี createApp

จากเดิมใน Vue 2 ถ้าเราจะสร้าง Application ขึ้นมา ก็จะใช้วิธีการ new Vue ขึ้นมาตรงๆ เลย

const app = new Vue({
    el: '#app',
    //TODO
})

แต่สำหรับ Vue 3 จะเปลี่ยนไปใช้คำสั่ง createApp แทน (ไม่สามารถสร้างเองได้แล้ว ต้องสร้างผ่าน factory function ที่ Vue เตรียมไว้ให้เท่านั้น)

const app = Vue.createApp({
    //TODO
})

app.mount('#app')

หรือ

import { createApp } from 'vue'

const app = createApp({
    //TODO
})

app.mount('#app')

อีกเรื่องหนึ่งคือการ mount แอพเข้ากับ html โดยใช้ el นั้นโดนตัดออกไปแล้ว

ไปใช้วิธีการ mount ด้วยเมธอด .mount() หลังจากสร้างแอพไปแล้วแทน ซึ่งเป็นการแยกส่วนโลจิคออกจากการกำหนดส่วนแสดงผล (HTML) ออกจากกัน ทำให้ตอนนี้เราสามารถสร้างแอพเปล่าๆ โดยยังไม่ต้อง mount ได้แล้ว ถ้าอยากเอาไปทำเทสเพิ่มก็ทำได้ง่ายขึ้น

data ต้องเป็น method เท่านั้น

ปกติ data ของ Vue 2 นั้นสามารถกำหนดเป็น object หรือ function ที่รีเทิร์น object กลับมาแบบไหนก็ได้

new Vue({
    data: {
        title: 'นี่คือ Title แบบ Vue 2',
    },
})

แต่สำหรับ Vue 3 ถูกกำหนดว่า data จะต้องเป็น function เท่านั้น

Vue.createApp({
    data(){
        return {
            title: 'นี่คือ Title แบบ Vue 2',
        }
    },
})

Component ผูกกับ app

ใน Vue 2 เวลาเราสร้างคอมโพเนนท์ เราจะสั่งผ่านตัวแปร Vue ที่เป็นระดับ global แปลว่าคอมโพเนนท์นี้สามารถเรียกใช้จาก Application ของ Vue ตัวไหนก็ได้

Vue.component('my-button', {
    template: `
        <button @click="handleClick">Click Me!</button>
    `,
    methods: {
        handleClick(){
            this.$emit('whenclick')
        }
    },
})

แต่สำหรับ Vue 3 แล้วการจะสร้างคอมโพเนนท์จะต้องสร้างให้แอพตัวใดตัวหนึ่งไปเลย

const app = Vue.createApp({
    //TODO
})

app.component('my-button', {
    emits: ['whenclick'], //optional
    template: `
        <button @click="handleClick">Click Me!</button>
    `,
    methods: {
        handleClick(){
            this.$emit('whenclick')
        }
    },
})

emits เป็น properties ที่จะกำหนด หรือไม่กำหนดก็ได้ หน้าที่ของมันคือเอาไว้เก็บชื่อเมธอดทั้งหมดที่คอมฑโพเนนท์ตัวนี้ทำได้ (มันก็คือ $emit อะไรได้บ้างนั่นแหละ) แต่การใส่ใน emits นั้นจะทำให้เวลาเรามาอ่านว่าคอมโพเนนท์ตัวนี้มีอะไรให้เรียกใช้ได้บ้างก็จะดูจากตรงนี้ได้เลย ไม่ต้องเสียเวลาไปไล่โค้ดข้างในอีกที

See the Pen
OJNGLEV
by Ta Tanapoj Chaivanichanan (@tanapoj)
on CodePen.

Vue Router ต้องสร้างด้วย createRouter()

เร้าเตอร์ก็เป็นอีกตัวที่มีการเปลี่ยนรูปแบบการเขียน

import Vue from 'vue'
import VueRouter from 'vue-router'

import App from './App.vue'
import FirstPage from './pages/FirstPage.vue'
import Page from './pages/FirstPage.vue'

Vue.use(VueRouter)

new Vue({
    render: (h) => h(App),
    router: new VueRouter({
        mode: 'history',
        routers: [
            { path: '/', component: FirstPage },
            { path: '/second', component: SecondPage },
        ],
    }),
}).$mount('#app')

โดยการสร้าง router จะต้องสร้างแยกตั้งหากด้วยคำสั่ง createRouter()

รวมถึงโหมด history ที่ตอนแรกเป็นค่าคอนฟิก, ใน Vue 3 ก็แยกออกมาเป็น createWebHistory() แล้วเหมือนกัน

import {createApp} from 'vue'
import {createRouter, createWebHistory} from 'vue-router'

import App from './App.vue'
import FirstPage from './pages/FirstPage.vue'
import Page from './pages/FirstPage.vue'

const router = createRouter({
    history: createWebHistory(),
    routers: [
        { path: '/', component: FirstPage },
        { path: '/second', component: SecondPage },
    ],
})

const app = createApp(App)
app.use(router)

router.isReady().then(() => {
    app.mount('#app')
})

Vuex ต้องสร้าง store ด้วย createStore()

คล้ายๆ กับข้อเมื่อกี้คือถ้าในโค้ดเรามีการใช้ Vuex การจะสร้าง store ขึ้นมาแทนที่จะ new Vuex.Store ตรงๆ ก็จะเปลี่ยนไปสร้างผ่าน createStore() แทน

import Vue from 'vue'
import Vuex from 'vuex'

import App from './App.vue'

const store = new Vuex.Store({
    //...
})

new Vue({
    store: store,
    render: (h) => h(App),
}).$mount('#app')

แบบนี้

import {createApp} from 'vue'
import {createStore} from 'vuex'

import App from './App.vue'

const store = createStore({
    //...
})

const app = createApp(App)
app.use(store)
app.mount('#app')

พวกค่าต่างๆ ของ store เช่น state, mutations, getters, actions ก็เซ็ตเหมือนเดิมทุกอย่าง ไม่มีอะไรเปลี่ยนแปลง

...

โดยรวมแล้ว Vue 3 มีการเปลี่ยน API ให้แยกส่วนกันมากขึ้น ทำให้โครงสร้างโค้ดถูกแบ่งเป็นโมดูลๆ จัดการและเทสง่ายขึ้น

Fragment

สำหรับใช้ที่เคยใช้ React มาก่อน Fragment ใน Vue ก็ใช้คอนเซ็ปเดียวกันนั่นแหละ

ตามปกติแล้วเวลาเราสร้าง template จำเป็นจะต้องมี root element 1 ตัวครอบทุกอย่างเอาไว้ ซึ่งหลายๆ ครั้งมันก็ไม่สะดวกเอาซะเลย

<!-- Layout.vue -->
<template>
  <div>
    <header>...</header>
    <main>...</main>
    <footer>...</footer>
  </div>
</template>

สำหรับ Vue 3 นั้นอนุญาตให้เราสร้าง root element หลายตัวใน template ได้แล้ว

<!-- Layout.vue -->
<template>
  <header>...</header>
  <main v-bind="$attrs">...</main>
  <footer>...</footer>
</template>

Teleport Component

teleport เป็นฟีเจอร์ที่ทำให้คอมโพเนนท์บางส่วนที่เราสร้างขึ้นมาใน Application สามารถ "เทเลฟอร์ท" หรือ "วาร์ป" ออกไปข้างนอกได้!

ตัวอย่างที่เข้าใจง่ายที่สุดน่าจะเป็น Modal หรือการที่มีกล่องเหรือเฟรมอะไรสักอย่างเด้งขึ้นมาซ้อนทับ content ของเราเป็นอีกเลเยอร์หนึ่ง

สำหรับ Vue เวอร์ชันก่อนๆ ที่ต้องเขียนทุกอย่างอยู่ในขอบเขตของ Application เท่านั้น

ถ้าเราจะสร้าง Modal ขึ้นมาก็จะต้องสร้างไว้ข้างในแอพนั้นแหละ

แต่สำหรับ Vue 3 เราสามารถกำหนดสิ่งที่เรียกว่า teleport เพื่อบอกว่าโค้ดตรงนี้นะ เราจะส่งมันออกไปแสดงผลข้างนอกแอพ!

จากเดิมเป็นโค้ดแบบนี้

const app = Vue.createApp({});

app.component('modal-button', {
  template: `
    <button @click="modalOpen = true">
        Open full screen modal!
    </button>

    <div v-if="modalOpen" class="modal">
      <div>
        I'm a modal! 
        <button @click="modalOpen = false">
          Close
        </button>
      </div>
    </div>
  `,
  data() {
    return { 
      modalOpen: false
    }
  }
})

ให้เราเพิ่ม <teleport to="body"> ลงไปครอบคอมโพเนนท์ส่วนที่ต้องการส่งออกไปข้างนอก (เช่นเคสนี้ส่งไปแสดงผลที่ชั้น body)

app.component('modal-button', {
  template: `
    <button @click="modalOpen = true">
        Open full screen modal! (With teleport!)
    </button>

    <teleport to="body">
      <div v-if="modalOpen" class="modal">
        <div>
          I'm a teleported modal! 
          (My parent is "body")
          <button @click="modalOpen = false">
            Close
          </button>
        </div>
      </div>
    </teleport>
  `,
  data() {
    return { 
      modalOpen: false
    }
  }
})

See the Pen
gOPNvjR
by Vue (@Vue)
on CodePen.


จริงๆ ยังมีอีกหลายฟีเจอร์ที่ Vue 3 มีการเพิ่มฝเปลี่ยนแปลง แต่อันนี้เลือกมาเฉพาะๆ ตัวที่คิดว่าสำคัญ

ป.ล. Vue 3 นั้นออกเวอร์ชัน 3.0.0 เรียบร้อยแล้ว แต่เฟรมเวิร์คหลัๆ บางตัวก็ยังไม่เสร็จดี เช่น router หรือ Vuex และสำหรับการติดตั้งจะต้องใช้ npm i [email protected] หากต้องการจะใช้เวอร์ชัน 3 (ถ้าใช้ npm i vue จะได้เวอร์ชัน 2) ซึ่งการเปลี่ยนแปลงให้ vue 3 เป็นตัวหลักแทนน่าจะดำเนินการเสร็จภายในสิ้นปี 2020 นี้

อ่านเพิ่มเติมได้ที่ Release Note นะ

Node.js กับ TypeScript

Node.js เป็นหนึ่งในเฟรมเวิร์คยอดนิยมสำหรับเขียนโปรแกรมฝั่ง Backend แต่เพราะมันสร้างมาตั้งแต่ปี 2009 ยุคที่ JavaScript ยังเป็นเวอร์ชัน ES5 อยู่เลย

โดยดีฟอลต์แล้ว Node.js เลยไม่ซัพพอร์ท TypeScript เลย ไม่เหมือนกับ Deno ที่เพิ่งสร้างขึ้นมาโดยซัพพอร์ท TypeScript เป็นค่า default ตั้งแต่แรก

เพื่อชีวิตที่ดีกว่า มาเซ็ตโปรเจค Node.js + Express ให้ใช้ TypeScript ได้กันเถอะ!

Step 1: ติดตั้ง TypeScript

สำหรับใครที่มี TypeScript อยู่แล้วข้ามสเต็ปนี้ไปได้เลยนะ

แต่ถ้าใครยังไม่มี ดูวิธีติดตั้งแบบง่ายๆ ได้ที่บทความ สอนวิธีเซ็ตโปรเจค TypeScript / มาใส่ไทป์ให้ JavaScript เพื่อลดความผิดพลาดในการเขียนโค้ดกันดีกว่า

Step 2: เริ่มสร้างโปรเจค

ปกติเราจะเขียนโค้ด Express หน้าตาประมาณนี้

const express = require('express')

const app = express()

app.get('/', (req, res) => {
    res.send('Hello World!')
})

app.listen(3000)

สมมุติว่าเซฟเป็นไฟล์ชื่อ app.js ละกัน วิธีที่จะเปลี่ยนมันเป็น TypeScript อย่างแรกเลยคือเปลี่ยนนามสกุลให้กลายเป็น app.ts

Step 3: @types

ปัญหาเมื่อเรานำโค้ด JavaScript ธรรมดามาเปลี่ยนเป็น TypeScript นั่นคือการที่ไทป์หายไป!

TypeScript Compiler หรือ tsc ไม่มีทางรู้ได้เลยว่าโค้ดที่เขียนๆ ขึ้นมาใน JavaScript แต่ละตัวมีไทป์เป็นอะไรบ้าง

ดังนั้นเลยต้องมีการ define ให้ TypeScript รู้จัก ซึ่งการทำแบบนั้นไม่ต้องถึงขั้นเขียนโค้ดใหม่ทั้งหมด แต่แค่เพิ่ม @types เข้าไปก็พอแล้ว!

ส่วนการติดตั้งก็ไม่ยาก มี npm ใช้ npm, มี yarn ใช้ yarn

//npm
npm i @types/express --save-dev

//yarn
yarn add @types/express --dev

ข้อสังเกตคือ library ยอดนิยมส่วนใหญ่จะมีการทำ types ไว้ให้อยู่แล้ว โดยชื่อของแพกเกจไทป์ส่วนใหญ่จะชื่อเดียวกับชื่อแพกเกจหลัก แต่เติม @types/ ไว้ข้างหน้า

จากนั้นเราก็กลับไปแก้โค้ดของเราอีกที

สำหรับ TypeScript นั้นจะต้องกำหนดไทป์ให้ตัวแปรทุกตัว เช่น Application, Request, Response ซึ่ง import มาจาก express ได้ตรงๆ เลย

import express, { Application, Request, Response } from 'express'

const app: Application = express()

app.get('/', (req: Request, res: Response) => {
    res.send('Hello World!')
})

app.listen(3000)

เวลาจะใช้งานก็ต้องคอมไพล์ให้ออกมาเป็น .js ซะก่อนนะ

Step 4: Watch File

จากสเต็ปที่แล้ว จะพบว่าระหว่างการ develop จะมีขั้นตอนเยอะมากในการรัน

  • ต้องคอมไพล์ TypeScript ด้วยคำสั่ง tsc ก่อน
  • รัน Node ด้วยคำสั่ง node
  • แล้วถ้ามีการแก้ไข้โค้ดอะไร ก็ต้อง kill process แล้วเริ่มคอมไพล์ตั้งแต่ TypeScript อีกรอบหนึ่งเลย
  • ซึ่งเป็นอะไรที่น่ารำคาญและทำให้ Productivity ต่ำมากๆ

ดังนั้นในสเต็ปสุดท้ายนี้เรามาดูวิธีการเซ็ตคำสั่ง ให้มัน watch file ให้เรากันดีกว่า

การ watch file หมายความว่า ให้ node คอยดูถ้าไฟล์ source code ของโปรแกรมมีการเปลี่ยนแปลง (เช่นมีการ save โค้ดตัวใหม่เข้ามา) ให้เริ่มรันโปรแกรมใหม่ด้วยตัวมันเอง เราจะได้ไม่ต้องมาคอยสั่งทุกครั้ง

ตามปกติถ้าเราเขียน Node.js ธรรมดา เราอาจจะใช้แพ็กเกจ เช่น nodemon

nodemon app.js

แต่ถ้าเราเขียนโค้ดในไฟล์ TypeScript อยู่ เราก็ต้องสั่งให้มัน watch file ด้วยอีกต่อหนึ่ง

tsc --watch

ซึ่งถ้าใช้วิธีนี้จะต้องเปิด Terminal ไว้ 2 อัน อันนึงรัน nodemon อีกอันรัน tsc นะ

หรือเราอาจจะใช้ ts-node แทนก็ได้ (อ่านวิธีใช้ ts-node และวิธีเซ็ต structure ของโปรเจคได้ที่ บทความสอนวิธีเซ็ตโปรเจค TypeScript)

nodemon --watch 'src/**/*.ts' --ignore 'src/**/*.spec.ts' --exec 'ts-node' src/app.ts

นั่นคือเราสั่งให้ nodemon คอยดูไฟล์ทั้งหมดในโฟลเดอร์ src ที่เป็นนามสกุล .ts ถ้าไฟล์มีการเปลี่ยนแปลง (มีการแก้ไขหรือมีการเซฟใหม่) ให้รันคำสั่ง ts-node ใหม่ทันที

หรือถ้าไม่อยากเขียน command ยาวๆ ก็ไปเขียน config ในไฟล์ nodemon.json แทนก็ได้

แบบนี้

{
  "watch": ["src"],
  "ext": "ts",
  "ignore": ["src/**/*.spec.ts"],
  "exec": "ts-node ./src/app.ts" 
  #or 
  "exec": "npx ts-node ./src/app.ts"
}

ใช้ ts-node-dev

หรือใช้อีกวิธีคือลงแพ็กเกจ ts-node-dev

# npm
yarn add ts-node-dev --dev

# yarn
npm i ts-node-dev --save-dev

แล้วก็รันด้วยคำสั่ง

ts-node-dev app.ts

จากที่เราได้รู้จักโลกของ UX UI ไปใน Section ที่แล้ว ใน Section นี้ เราจะมาเข้าใจให้ลึกขึ้นอีกนิด สำหรับ UX UI Design โดยมีคำกล่าวสั้นๆว่า

UX คือ นามธรรม
UI คือ รูปธรรม

และในพื้นฐานแรก ที่เราจะมาเริ่มเรียนรู้คือ UI Design


เคลียร์กันชัดๆ UI Design คืออะไร?

นิยามของ UI Design คือการออกแบบสิ่งที่เชื่อมประสานระหว่างผู้ใช้กับสิ่งใดสิ่งหนึ่ง

ตัวอย่าง :: หากมีไอศกรีมอยู่ 1 ถ้วย ตัวกลางระหว่างตัวคุณกับไอศกรีมคือช้อน ซึ่งในที่นี้ ช้อนเปรียบเสมือน UI ตรงที่ถ้าไอศกรีมถ้วยนี้เป็นทรงเตี้ยช้อนที่ถูกออกแบบมาจะต้องเป็นทรงสั้น หรือถ้าไอศกรีมถ้วยนี้เป็นแบบทรงสูงช้อนก็จะต้องถูกออกแบบมาให้เป็นทรงยาว ดังนี้ การออกแบบที่ดี คือจะต้องออกแบบช้อนให้สะดวกสบายต่อการตักไอศกรีมในถ้วยทรงต่างๆนั้น

ซึ่งในกรณีของ Mobile Application หรือ Website นี้ สิ่งที่เป็นตัวเชื่อมประสานระหว่างคุณกับ Content (เนื้อหาข้อความต่างๆ โดยจะรวมไปถึง ภาพ, วีดีโอ และอื่นๆ) ก็คือ หน้าWebsite / Application

ดังนั้น การออกแบบ UI Design ของ Website หรือ Mobile Application ก็คือการสร้างเส้นทางตัวเชื่อมประสานให้กับผู้ใช้งานเพื่อไปสู่เป้าหมายที่ตั้งไว้ได้สำเร็จ


เคลียร์กันชัดๆ UX Design คืออะไร?

UX Design เป็นสิ่งที่จับต้องไม่ได้ นิยามของ UX Design คือการออกแบบประสบการณ์ของผู้ใช้งาน ซึ่งประสบการณ์เป็นเรื่องของความรู้สึก การที่เราจะเกิดประสบการณ์ต้องเกิดจากการรับรู้ควบคู่ไปกับความรู้สึก

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

ดังนั้น ประสบการณ์ที่ได้กินไอศกรีมผ่านช้อน หรือความรู้สึกที่ได้ชมภาพยนต์ผ่าน Website ก็คือประสบการณ์ที่ถูกออกแบบขึ้นมา

การออกแบบ UX Design ของ Website และ Mobile Application จะสร้างประสบการณ์ การจดจำ ความรู้สึกที่ดี และนำพาให้ผู้ใช้งานกลับมาใช้งานอีกครั้ง ซึ่งสิ่งเหล่านี้คือ เป้าหมายที่แท้จริงของผู้ออกแบบ


องค์ประกอบที่ต้องเรียนรู้สำหรับการออกแบบ

ในด้านของ UX Design จะเรียนรู้กระบวนการหรือแนวคิดที่เป็นเครื่องมือต่างๆ

  • Design Thinking :: เป็นเครื่องมือหรือกระบวนการที่ให้ความสำคัญกับการทำความเข้าใจผู้ใช้

  • Service Design :: เป็นกระบวนการที่เน้นการออกแบบสำหรับบริการเป็นหลัก โดยมีคอนเซ็ปว่า Don't speak just doing

  • Design Sprint :: เป็นกระบวนการออกแบบที่ได้ถูกพัฒนาขึ้น จุดเด่นคือเน้นความเร็วเป็นสำคัญ โดยจะจบได้ใน 5 วัน แต่มีประเด็นที่สำคัญคือ Design Sprint นั้นจะใช้กับผลิตภัณฑ์หรือบริการที่ออกสู่ตลาดแล้วเท่านั้น

  • User Centered Design :: เป็นแนวคิดในการออกแบบที่มุ่งเน้นให้ความสำคัญกับผู้ใช้งานเป็นหลัก โดยการคิดแก้ปัญหาจะมุ่งเน้นไปที่ผู้ใช้งานเป็นสำคัญ

ในด้านของ UI Design จะเน้นโครงสร้างและองค์ประกอบของการออกแบบ

  • Information Design :: เป็นการออกแบบข้อมูล ที่เน้นการนำเสนอข้อมูลที่สร้างความน่าสนใจ สร้างความเข้าใจ และเกิดการเรียงลำดับของข้อมูลที่ถูกต้อง

  • Interaction Design :: เป็นกระบวนการการออกแบบที่เน้นการตอบโต้หรือการตอบสนองที่ถูกต้อง และนำทางผู้ใช้ไปยังเป้าหมายที่ต้องการ

  • Information Architect :: เป็นเรื่องของการจัดกลุ่มข้อมูล การเรียงลำดับข้อมูล การจัดโครงสร้างของข้อมูล ให้มีความถูกต้องและเข้าใจได้ง่ายเพื่อให้ผู้ใช้งานรู้ลำดับก่อน-หลังการเข้าถึงข้อมูลได้

  • Visual Design :: เป็นการออกแบบที่เน้นการนำเสนอภาพที่มีองค์ประกอบต่างๆ เช่น การจัดเลเอ้าท์, การใช้สี, การใช้ตัวอักษร, การใช้โครงสร้าง, การใช้รูปทรง และรวมไปถึงการใช้พื้นที่ว่างในการนำเสนอภาพให้ผู้ใช้งานได้เข้าใจ

  • Human Computer Interaction :: เป็นศาสตร์การออกแบบที่เฉพาะเจาะจงโดยพูดถึงความสัมพันธ์ระหว่างมนุษย์กับ Computer เมื่อสองสิ่งนี้ต้องมาทำงานร่วมกัน จะมีเอกลักษณ์เฉพาะบางอย่าง ทั้งในเรื่องของความยืดหยุ่น ความหลากหลายการปรับเปลี่ยน โดยปัจจุบันยังมีการพัฒนาอย่างไม่หยุดยั้ง


กรณีตัวอย่างการออกแบบ UX UI สำหรับ Mobile Application

การเรียนรู้ที่ดีที่สุด คือการเรียนรู้จากงานที่สำเร็จเสร็จสิ้นแล้ว

ปัจจุบันมีผู้ใช้งาน Mobile Application เยอะกว่า Website ผ่าน PC Computer มากขึ้น 5 เท่า!!

โดยองค์ประกอบของการออกแบบ Mobile App คือ

  • การออกแบบข้อมูล
  • การออกแบบการตอบสนองหรือการตอบโต้
  • การออกแบบรูปทรง สี และตัวอักษร
    ขึ้นอยู่กับเป้าหมายของผู้ใช้งานเป็นสำคัญ และเนื้อหาที่เราต้องการนำเสนอ

ตัวอย่างการออกแบบ UI ของ Mobile App

ตัวอย่างที่ 1 "Facebook Application" :: การออกแบบหน้าแรกของ Facebook เน้นการเล่าเรื่องราวต่างๆ โดยจะแบ่งออกเป็น 3 ส่วน ดังนี้

ตัวอย่างที่ 2 "NTC Application" :: ซึ่งเป็น App แนะนำวิธีการออกกำลังกายที่มีการออกแบบการจัดหมวดหมู่ที่ดี เพราะเป็น Application ที่มีข้อมูลเยอะมาก ทำให้ต้องแยกข้อมูลให้ง่ายและสะดวกต่อการเข้าถึงของผู้ใช้งาน ดังนี้

ตัวอย่างที่ 3 "TED Application" :: เป็น Application ที่นำเสนอข้อมูลเป็นคลิปวีดีโอต่างๆของงาน TED ที่มีคนหลากหลายอาชีพ มาเล่าประสบการณ์ต่างๆให้ฟัง

ตัวอย่างที่ 4 "Unsplash Application" :: เป็น Application ที่นำเสนอในเรื่องของรูปภาพ ดังนั้นจึงใช้การนำเสนอที่เน้นรูปภาพเป็นหลัก มีการลดรายละเอียดที่เป็นส่วนของข้อความออกไป

ตัวอย่างที่ 5 "Line Man Application" :: นำเสนอด้วยข้อมูลจำนวนมาก เน้นข้อความและย่อรูปภาพให้เล็กลง เน้นการนำเสนอเนื้อหา และ Content เยอะๆ พร้อมๆกัน เพื่อให้ผู้ใช้เห็นบริการทั้งหมดที่มี โดยเราจะเห็นดีไซน์แบบนี้ได้ใน Application ที่เกี่ยวกับ E-Commerce


กรณีตัวอย่างการออกแบบ UX UI สำหรับ Website

สิ่งสำคัญของการออกแบบ Website คือ การออกแบบจุดที่ผู้ใช้ควรสนใจ ดังนั้นการออกแบบ Website ยังคงให้ความสำคัญกับเป้าหมายผู้ใช้งาน และเนื้อหาในการนำเสนอ เป็นสิ่งสำคัญหลัก

ตัวอย่างการออกแบบ UI ของ Website

ตัวอย่างที่ 1 "Facebook" :: เน้นส่วนที่สำคัญตรงกลาง

ตัวอย่างที่ 2 "Netflix" :: นำเสนอด้วยภาพตัวอย่างภาพยนต์ขนาดเล็กจำนวนมากพร้อมๆกัน เพื่อให้ผู้ใช้เห็นข้อมูลได้เยอะ และเลือกดูได้ตามความสนใจ

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


กรณีตัวอย่างการเรียนรู้การออกแบบ UX UI จากความผิดพลาด

  • เกิดจากการที่เราให้ความสำคัญกับข้อมูลไม่ถูกต้อง
  • ไม่สามารถเรียงลำดับความสำคัญของข้อมูลได้

หนึ่งในคำถามที่เว็บโปรแกรมเมอร์มือใหม่ถามกันเยอะมากจนน่าจัดเก็บไว้เป็น FAQ เลยก็คือ

"จะทำยังไงให้เราเรียกใช้ฟังก์ชันภาษา PHP จากสคริป JavaScript ได้"

เช่นแบบนี้...

<button onclick="<?php functionInPhp1(); ?>">
    คลิกฉันสิ!
</button>

หรือแบบนี้...

function functionInJs(){
    let x = <?php functionInPhp2(); ?>
}

คำตอบคือ ด้วยการทำงานของเว็บที่ทำงานบนโปรโตคอล http นั้น...มันทำไม่ได้!! (แต่มีวิธีแก้ ถ้าอยากทำจริงๆ อ่านต่อไป!)

จริงๆ แล้วไม่จำกัดว่าต้องเป็นภาษา PHP เท่านั้นนะ เคสนี้เป็นกับทุกภาษาฝั่งเซิร์ฟเวอร์เลย

เพื่อจะตอบว่าทำไมมันทำไม่ได้ เราจะต้องอธิบายการทำงานของ http กันซะก่อน

http และ Stateless

http เป็นโปรโตคอลมาตราฐานสำหรับการเขียนเว็บ ซึ่งการทำงานของมันสรุปง่ายๆ ได้ดังนี้

โปรโตคอล (Protocol) = กฎที่ตั้งขึ้นมาเพื่อให้คอมพิวเตอร์ในเน็ตเวิร์คสามารถคุยกันด้วยภาษาเดียวกัน ไม่งั้นมันจะคุยกันไม่รู้เรื่อง

  • Client ส่งคำขอหรือ request ไปหา Server
  • เมื่อ Server ได้รับ request แล้วก็จะรันสคริปที่เตรียมไว้ เพื่อหาว่าจะตอบอะไรกลับไปให้ Client, ในสเต็ปนี้ อาจจะมีการเชื่อมต่อเพื่อขอข้อมูลจาก database ด้วย
  • หลังจาก Server คิดเสร็จ ก็จะส่งคำตอบ (อยู่ในรูปแบบของ String) กลับไปให้ Client [มาถึงตรงนี้ถือว่า Server ทำงานเสร็จแล้ว!]
  • Client รับข้อมูลไป (ส่วนใหญ่จะอยู่ในรูปแบบ html) ก็เอาไปแสดงผล แต่ถ้ามีการแนบสคริปมาด้วย ก็จะจัดการรันสคริปตัวนั้นซะในสเต็ปนี้
  • จบจ้า!

สำหรับฝั่ง Client นั้นไม่ค่อยมีปัญหาเพราะมีแค่ภาษาเดียวเท่านั้นที่ครอบครองอยู่ นั่นคือ JavaScript แต่ฝั่ง Server นี่มีหลายภาษามากๆ เช่น PHP, Node.js. Go, .NET

แต่ไม่ว่าฝั่งเซิร์ฟเวอร์จะเขียนด้วยภาษาอะไร หน้าที่ของมันคือส่ง HTML, CSS, JS กลับมาให้ Client เพื่อโปรเซสต่อ

จะเห็นว่า http เป็นโปรโตคอลง่ายๆ ถามมา-ตอบกลับ แล้วก็จบงาน

ซึ่งเราเรียกการทำงานแบบนี้ว่า "Stateless" คือทำงานเป็นรอบ พอเรียกใช้งานและทำงานนั้นเสร็จแล้ว ก็จบการทำงาน (เว็บส่วนใหญ่ทำงานแบบนี้)

ตรงข้ามกับ "Stateful" ที่ตัวโปรแกรมรันค้างอยู่ตลอดเวลา (ให้นึกถึงแอพพลิเคชันมือถือหรือโปรแกรมที่รันใน Desktop)

Server ทำงานก่อน Client เสมอ!

เราอธิบายให้ฟังแล้วว่า http นั้นเริ่มทำงานที่ Server รันเพื่อโปรเซสข้อมูลที่จะส่งกลับมาให้ Client ก่อน ... แล้วพอ Client ได้รับข้อมูล (ซึ่งอาจจะมี JavaScript แนบติดมาให้ด้วย) ก็จะเอาสคริปตัวนั้นมารันต่อ

แสดงว่าในจังหวะที่ Client เริ่มทำงานนั้น ... โค้ดฝั่ง Server ทำงานเสร็จไปแล้ว !

นี่เลยเป็นเหตุผลว่าทำไมเราไม่สามารถทำให้ JavaScript เรียกให้ PHP ทำงานได้

เช่น

<?php
    function registerMeeting(){
        //ต้องการบันทึกว่าเข้าร่วมประชุมแล้ว
    }

    function getOnlines(){
        //ต้องการดึงรายชื่อคนที่กำลังออนไลน์อยู่ในขณะนี้
    }
?>

<button onclick="<?php registerMeeting(); ?>">
    ลงชื่อเข้าประชุม
</button>

<script>
    function getWhoOnlineNow(){
        let onlines = <?php getOnlines(); ?>
    }
</script>

ในโค้ดตัวอย่างนี้เรามีฟังก์ชันในภาษา PHP อยู่ 2 ตัว คือ registerMeeting() และ getOnlines()

จากนั้นเราไปเขียนโค้ด JavaScript เพื่อเรียกใช้งานฟังก์ชัน PHP ทั้งสองตัวนี้ต่อ

แต่ปัญหาก็คือ PHP เป็น Server-Side-Script มันทำงานก่อนเสมอ (ไม่ต้องรอให้ JavaScript เรียกหรอก ฉันทำงานเองตอนนี้เลย!)

แต่ด้วยโลจิคแล้ว เราต้องการให้ฟังก์ชันพวกนี้ทำงานเมื่อเรามี event เท่านั้น (เชื่อ ปุ่มโดน onclick หรือฟังก์ชัน JavaScript ทำงาน)

ดังนั้นโค้ดนี้เลยผิด!

Asynchronous คือทางแก้

หากต้องการให้ JavaScript เรียกให้ PHP ทำงานได้ มีอยู่วิธีเดียวนั้นคือใช้เทคนิคการเขียนโปรแกรมแบบ Asynchronous

หรือถ้าจะเรียกด้วยชื่อแบบดังเดิมคือเทคนิคที่เรียกว่า "Ajax" (Asynchronous JavaScript and XML) ... แต่ปัจจุบันไม่ค่อยเรียกชื่อนี้กันแล้วนะ และเราก็ไม่ได้ใช้แค่ XML เป็นตัวกลางส่งข้อมูลกันอีกตัวไป มีการใช้ JSON เพิ่มเข้ามาด้วย

ในบทความนี้จะไม่สอน Ajax แบบละเอียดนะ ถ้าอยากรู้ตามไปอ่านได้ที่ Ajax คืออะไร แล้วมันใช้ยังไง?

สำหรับ PHP ...

ให้แยกโค้ดส่วนที่ต้องการให้ JavaScript เรียกใช้งานได้ออกมาอยู่อีกไฟล์หนึ่ง เช่นกรณีนี้ตั้งชื่อไฟล์ว่า async-handler.php

<?php
//FILE: async-handler.php

function registerMeeting(){
    //ต้องการบันทึกว่าเข้าร่วมประชุมแล้ว
}

function getOnlines(){
    //ต้องการดึงรายชื่อคนที่กำลังออนไลน์อยู่ในขณะนี้
}

switch($_GET['action']){
    case 'register-meeting': 
        registerMeeting(); 
        break;
    case 'get-online-user': 
        getOnlines(); 
        break;
}

และเนื่องจากเรามี action ที่ต้องการให้ทำงานมากกว่า 1 ตัว ก็เลยใช้ query-string ชื่อว่า action เป็นตัวแยกว่า request ครั้งนี้ต้องการให้ฟังก์ชันไหนทำงาน (ตรงนี้ตั้งชื่อว่าอะไรก็ได้นะ แล้วแต่เลย)

<button onclick="registerMeeting()">
    ลงชื่อเข้าประชุม
</button>

<script>
    function registerMeeting(){
        fetch('/async-handler.php?action=register-meeting')
    }

    function getWhoOnlineNow(){
        fetch('/async-handler.php?action=get-online-user')
        .then(onlines => {
            ...
        })
    }
</script>

จากนั้น ในฝั่ง JavaScript ก็ใช้การ request กลับไปยังไฟล์ PHP async-handler.php ที่เตรียมไว้อีกรอบ จะใช้คำสั่ง fetch() หรือไลบรารี่ Axios หรือถ้าเก่าหน่อยก็ใช้ $.ajax() ของ jQuery ก็ตามสะดวกเลย

สรุป

การจะให้ JavaScript เรียกคำสั่ง PHP ตรงๆ นั้นทำไม่ได้ เพราะกว่า JavaScript จะเริ่มทำงาน PHP ก็ทำงานจนเสร็จไปก่อนแล้ว

แต่มีวิธีการแก้ทางคือสร้าง request ขึ้นมาอีกครั้งเพื่อเรียกไปหา Server ให้ปลุก PHP ขึ้นมาทำงานอีกรอบหนึ่ง

คือต้อง request 2 ครั้ง

  • ครั้งแรก - ให้ Server ส่ง HTML, CSS, JS มาให้ก่อน
  • ครั้งที่สอง - JavaScript สร้าง request อีกครั้ง เรียกไปยังไฟล์ PHP ที่เตรียมเป็น asynchronous handler เอาไว้

วันนี้ผมจะมาแนะนำและวิธีการใช้งานเบื้องต้นของ plugin ที่น่าสนใจตัวหนึ่งที่มีชื่อว่า
"Google Maps for Flutter"
โดย plugin ตัวนี้จะให้ Google Maps ที่เป็น Widget มาให้เราได้เปิดใช้งานแผนที่ของกูเกิ้ล

ขั้นตอนการติดตั้ง

อันดับแรก เราต้องทำการขอ API Key ที่ลิ้งค์ https://cloud.google.com/maps-platform/
เมื่อเข้ามาหน้าเว็บไซต์แล้วให้เข้าไปที่ Console (ตรงขวามุมบนของหน้าจอ)

สร้าง Project ของเราขึ้นมาก่อน

เมื่อทำการสร้างเสร็จแล้วให้เปิดแท็บด้านขวามือ แล้วเลือกเมนูที่ชื่อว่า Google Maps

Google Maps จะมี​ API ให้ใช้หลายตัว เราสามารถเข้าไป Enable เพื่อที่จะเรียกใช้ API เหล่านั้นได้
แต่ตอนนี้เราจะเลือก Enable Maps SDK for Android / IOS เพื่อที่จะเอา API Key ไปเรียกใช้งาน API เหล่านี้

ต่อมาให้เข้าไปที่เมนู Credentials เพื่อที่จะสร้าง API Key เอาไปแปะในโค้ดให้เชื่อมต่อกับ Google Cloud Platform
กดเลือก Create Credentials -> API Key

เราก็จะได้ API Key มาเท่านี้ก็จะสามารถเชื่อมต่อกับ Google Map Api ได้

มาในส่วนของการเขียนโค้ดกันบ้าง

สำหรับ Android ให้เข้าไปเพิ่ม API Key ที่ไฟล์ AndroidManifest.xml ในโฟลเดอร์
Android (android/app/src/main/AndroidManifest.xml)

.
└── android
    └── app
        └── src
            └── main
                └── AndroidManifest.xml

ให้เพิ่ม เพื่อขอ permission กับ เพื่อเพิ่ม API KEY เข้าไป

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.fluttergooglemap">

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="fluttergooglemap"
        android:icon="@mipmap/ic_launcher">

        <meta-data android:name="com.google.android.geo.API_KEY"
            android:value="YOUR API KEY"/>

        <activity
            android:name=".MainActivity"
            ...

สำหรับ IOS เข้าไปที่ไฟล์ AppDelegate.swift (ios/Runner/AppDelegate.swift)

.
└── ios
    └── Runner
        ├── AppDelegate.swift
        └── Info.plist

เพิ่ม API KEY เข้าไป GMSServices.provideAPIKey("YOUR KEY HERE")

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
  GMSServices.provideAPIKey("YOUR API KEY")
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

และเข้าไปที่ไฟล์ info.plist เพิ่มคำส่ัง เพื่อขอ permission

<dict>
     <key>NSLocationWhenInUseUsageDescription</key>
          <string>This app needs your location to test the location feature of the Google Maps plugin.</string>
          <key>io.flutter.embedded_views_preview</key>
          <true/>
     ...

เข้าไปที่ไฟล์ pubspec.yaml
ติดตั้ง google_maps_flutter: ^0.5.28+1 (เวอร์ช้่นล่าสุดเมื่อ May 21, 2020)

dependencies:
  flutter:
    sdk: flutter

  google_maps_flutter: ^0.5.28+1

  ...

import Libray

import 'package:google_maps_flutter/google_maps_flutter.dart';

สร้างตัวแปรประเภท GoogleMapController คือ class ที่เอาไว้สร้าง Future อีกที เอาไว้ควบคุมการทำงาน

class _MyHomePageState extends State<MyHomePage> {

  Completer<GoogleMapController> _controller = Completer();

Library จะมี Widget มาให้ชื่อว่า GoogleMap()

ทดลองพิมพ์ตามโค้ดด้านล่างนี้

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: GoogleMap(
        initialCameraPosition: CameraPosition(
          target: LatLng(13.757429, 100.502465), //กำหนดพิกัดเริ่มต้นบนแผนที่
          zoom: 15, //กำหนดระยะการซูม สามารถกำหนดค่าได้ 0-20
        ),
        onMapCreated: (GoogleMapController controller) {
          _controller.complete(controller);
        },
      ),
    );
  }

เริ่มต้น GoogleMap จะต้อง initialCameraPosition เสมอ โดยกำหนดพิกัดจุดเริ่มต้นสถานที่จะให้ GoogleMap แสดงขึ้นมา แล้วลอง Run

เพียงเท่านี้ก็จะสามารถเปิดกูเกิ้ลแมพได้ บทความนี้จะเป็นการติดตั้งเบื้องต้น และบทความต่อไปจะเป็นการใช้งานเบื้องต้นเกี่ยวกับ GoogleMap, Polyline, Marker