History API คืออะไร? + สอนวิธีใช้

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

History API ไม่ใช่ของใหม่

โดยปกติแล้ว web browsers จะมีการเก็บ “ประวัติการเข้าชมเว็บเพจ” ทุกครั้งที่มีการเปลี่ยนหน้าใหม่ history api ก็คือสิ่งที่ทำให้เราสามารถเข้าไปจัดการกับประวัติเหล่านั้นได้นั่นเอง

history api ประกอบไปด้วย methods(สั่งให้ทำ) และ properties(ดูข้อมูล) ต่างๆ ซึ่งในการจะใช้งานนั้น เราจะต้องทำผ่านทาง object ของ javascript ที่มีชื่อว่า window.history

Back & Forward (Method)

ทั้ง 2 methods นี้จะทำหน้าที่เหมือนกับการกดปุ่ม back และ forward ที่ web browsers

Go (Method)

เราสามารถกำหนดจำนวนหน้าที่เราต้องการให้ back หรือ forward ได้ด้วย method go() โดย parameter ที่เราจะต้องส่งให้ method นี้ก็คือ “จำนวนขั้น” ที่จะเดินหน้าหรือถอยหลัง หากจำนวนขั้นเป็นบวก จะถือว่าเป็นการ forward แต่ถ้าจำนวนขั้นเป็นลบก็จะถือเป็นการ back

Length (Property)

length จะมีประโยชน์ในการหาจำนวนของ history ทั้งหมด ซึ่งก็คือจำนวนหน้าที่เราได้เคยเปิดไปนั่นเอง

ปัญหา

เราจะเห็นว่า web application สมัยนี้ นิยมใช้ Ajax ในการโหลด content แบบ dynamic ข้อดีของวิธีนี้ก็คือ users จะสามารถได้รับ content ที่พวกเขาต้องการได้ทันทีโดยที่ไม่ต้องโหลดใหม่หมดทั้งหน้า แต่วิธีนี้ก็มีข้อเสียอยู่เหมือนกัน

สมมติเรากำลังอ่านข่าวดาราจากเว็บๆ หนึ่ง เราพบว่าที่ด้านล่างของเนื้อหาข่าวมี gallery อยู่ เมื่อเราลองกดดูรูปดาราไปเรื่อยๆ เราพบว่ารูปใหม่นั้นถูกโหลดเข้ามาใน container ของ gallery โดยที่เนื้อหาส่วนอื่นๆ ยังคงนิ่งเหมือนเดิม นี่คือ gallery ที่เขียนโดยใช้ Ajax

เมื่อดูไปสักพัก เราพบว่ารูปที่ 9 นั้น เป็นรูปดาราที่เราชอบ เราจึงอยากแชร์หน้านี้ไปให้เพื่อนๆ ดูบ้าง แต่พอเพื่อนๆ ได้ดูหน้าที่เราแชร์ไปนั้น พวกเขากลับพบว่ามันเป็นรูปที่ 1 ไม่ใช่รูปที่ 9 ทำไมถึงเป็นแบบนี้ ?

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

History API ใน HTML5

เพื่อเป็นการแก้ไขปัญหาดังกล่าว html5 จึงได้เพิ่ม features ใหม่ๆ เข้ามาใน history api ดังนี้

pushState (Method)

method นี้จะเอาไว้เพิ่ม history entry ใหม่เข้ามาในรายการ history ทั้งหมด โดยปกติแล้ว entry ใหม่จะถูกเพิ่มเข้ามาก็ต่อเมื่อมีการเปลี่ยนหน้า แต่ใน html5 เราสามารถเพิ่มเองได้แล้ว โดย parameters ที่ใช้จะมีอยู่ 3 ตัว ด้วยกัน ดังนี้

  • dataข้อมูลเกี่ยวกับ history นั้นๆ
  • titleชื่อเรียก history นั้นๆ
  • urlurl ที่เราต้องการจะให้แสดงที่ address bar

replaceState (Method)

method นี้จะคล้ายกับ pushState เลย แต่จะต่างกันตรงที่ replaceState จะเป็นการ “แก้ไข” history ปัจจุบัน ไม่ใช่ “เพิ่ม” (การใช้ pushState จะทำให้ window.history.length มีค่าเพิ่มขึ้น ซึ่งต่างจากการใช้ replaceState ที่ window.history.length ยังคงมีค่าเท่าเดิม)

state (Property)

property นี้จะเอาไว้สำหรับเรียกดู data ของ history ปัจจุบัน ซึ่ง data นี้ก็คือ data ที่เราได้ใส่เข้าไปตอนใช้ method pushState หรือ replaceState นั่นเอง

popstate (Event)

popstate นั้นเป็น event ที่จะ “ทำงาน” ทุกครั้งที่ users กดปุ่ม back หรือ forward หรือเมื่อมีการสั่งให้ method back(), forward() หรือ go() ทำงาน

นอกจากนี้ เรายังสามารถเข้าไปดู data ของ history หลังจาก event popstate ทำงานได้ โดยดูผ่าน property state ของ event object ที่ส่งผ่านไปยัง callback function ลองดูตัวอย่างนี้

จากโค้ดด้านบนจะเห็นว่าเราจะไม่ใช้ window.history.state เพราะมันจะไปดึง data ของ history entry ปัจจุบันมาให้ แต่สิ่งเราต้องการจริงๆ แล้วก็คือ data ของ history entry ที่เรากำลังจะไปด้วย method back(), forward() หรือ go()

Workshop – History API

หลังจากที่เรารู้แล้วว่าแต่ละ methods, properties และ event ของ history api นั้นมีวิธีใช้งานอย่างไร เราก็มาลองลงมือทำกันเลยดีกว่า สมมติเราจะสร้างหน้า gallery ขึ้นมาสักหน้าหนึ่ง โค้ดของเราจะเป็นแบบนี้

HTML หน้ารวมรูปทั้งหมด (index.html)

ในหน้ารวมรูปจะประกอบไปด้วยรูป thumbnails ทั้งหมด 4 รูปด้วยกัน ในแต่ละรูปจะมี link ที่จะพาไปยังหน้าสำหรับแสดงรูปนั้นๆ ส่วน container ของ gallery ให้เราปล่อยว่างไว้ก่อน

HTML หน้าแสดงรูปทั้ง 4 หน้า (1.html, 2.html, 3.html, 4.html)

หน้าแสดงรูปจะคล้ายกับหน้ารวมรูปเลย เพียงแต่เราจะต้องใส่ img element เพื่อที่จะแสดงรูปของหน้านั้นๆ เพิ่มเข้าไปใน container ของ gallery

เมื่อสร้างหน้ามาครบแล้ว ให้เราลองกดเปลี่ยนรูปดู เราจะพบว่ามันต้องโหลดใหม่หมดทั้งหน้า จริงๆ แล้ว ในส่วนของรูป thumbnails ด้านบนนั้นเหมือนกันทุกๆ หน้า เป็นไปได้มั้ยที่เราจะโหลดใหม่เฉพาะส่วน container ของ gallery ?

โหลด Content แบบ Dynamic ด้วย JavaScript

เนื่องจากเราไม่อยากให้ users ต้องโหลดใหม่หมดทั้งหน้า เราจึงเลือกใช้วิธีโหลด dynamic content ด้วย javascript แทนการสร้างหน้า html สำหรับแสดงแต่ละรูป เราจึงเขียนโค้ด javascript แบบนี้ (ขอใช้ jQuery เพื่อให้ง่ายต่อการทำความเข้าใจ)

เมื่อลองพรีวิวดู เราจะเห็นว่ารูปใหม่ถูกโหลดเข้ามาใน container โดยที่ไม่ต้องโหลดใหม่ทั้งหน้า แต่หากสังเกตดีๆ เราจะพบว่า url ของหน้านั้นยังคงเหมือนเดิมตลอด ไม่ได้เปลี่ยนไปตามรูป

ใช้ History API ในการเปลี่ยน URL ที่ Address Bar

เพื่อแก้ปัญหาดังกล่าว เราจึงใช้ pushState เข้ามาช่วย “เปลี่ยน url แบบ manual” โดยก่อนจะใช้ pushState ให้เราดึงข้อมูลที่เกี่ยวกับหน้าที่เรา “กำลังจะไป” มาให้ครบก่อน

จะเห็นว่าเราแยกโค้ดส่วนที่ไป “ดึงรูปมาแสดงใน container” ออกมาเป็นฟังก์ชัน getImage() เพื่อจะได้สะดวกในการนำมาใช้ซ้ำ

รองรับการ Back, Forward โดยใช้ popstate

จากโค้ดก่อนหน้า หากมีการกดปุ่ม back หรือ forward ที่ web browser เราจะพบว่า url ที่ address bar สามารถแสดงผลได้อย่างถูกต้องแล้ว แต่ที่ container ของ gallery กลับว่างเปล่า ทำไมถึงเป็นเช่นนี้ ?

สาเหตุก็คือ pushState นั้นมีหน้าที่แค่ “เก็บ” เพียงอย่างเดียว ไม่ใช่ “แสดง” เรานึกขึ้นได้ว่าการกดปุ่ม back หรือ forward ที่ web browser นั้นจะไปทำให้เกิด event popstate ขึ้น เราจึงจะอาศัย event นี้ในการแสดงรูปที่ container ของ gallery ลองดูโค้ดต่อไปนี้

เนื่องจากเราได้ “เก็บ” ข้อมูลทั้ง title และ src ของรูปเอาไว้ใน history เมื่อตอนที่เรา pushState แล้ว เราจึงสามารถนำข้อมูลเหล่านั้นออกมาใช้เพื่อสั่งให้ฟังก์ชันสำหรับแสดงรูปทำงานได้ทันที

เพียงขั้นตอนเท่านี้ gallery ของเราก็จะสมบูรณ์แบบ users สามารถเลือกดูรูปภาพได้อย่างรวดเร็วโดยไม่ต้องโหลดหน้าใหม่ สามารถ bookmark หรือแชร์ url ของแต่ละรูปได้ และยังรองรับการกดปุ่ม back และ forward ที่ web browser อีกด้วย

History API ไม่ได้สร้างหน้าใหม่

จะเห็นว่า history api นั้นไม่ได้สร้างหน้าขึ้นมาใหม่แต่อย่างใด มันเป็นเพียง “เครื่องมือ” ที่ใช้จัดการกับประวัติการเข้าชมหน้าเว็บเท่านั้นเอง สมมติว่า users กดเลือกดูรูปที่ 4 แล้วต้องการจะแชร์ไปให้เพื่อนๆ ดูบ้าง url ที่แชร์ก็จะเป็นแบบนี้

แน่นอนว่าการเข้า url ที่แชร์มาแบบตรงๆ จะทำให้โค้ด javascript ที่เราเขียนเพื่อใช้โหลด content แบบ dynamic ไม่ทำงาน เราจึงจะต้องเตรียมหน้าสำหรับแสดงรูปแบบปกติเอาไว้เสมอ (ซึ่งเราได้สร้างไว้ตั้งแต่ขั้นตอนแรกแล้ว)

Browser Compatibility + Polyfill

ข่าวดีก็คือ เราสามารถใช้ history api กับ web browsers ส่วนใหญ่ในปัจจุบันได้แล้ว แต่อาจมีปัญหาเล็กน้อยกับ Internet Explorer ที่จะรองรับตั้งแต่เวอร์ชัน 10 ขึ้นไป เราอาจใช้ polyfill อย่าง history.js เข้ามาช่วย โดย polyfill นี้จะใช้วิธี hash เป็น fallback หากพบว่า web browser นั้นยังไม่รองรับ history api

github

github ใช้ History API ในการ browse ไฟล์

เริ่มใช้ History API เสียแต่วันนี้ !

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

DemoSource
(Visited 9,072 times, 1 visits today)

4 Responses to “History API คืออะไร? + สอนวิธีใช้”

  1. l2aelba says:

    แนะนำ Plug-in ตัวนี้ครับ ผมใช้มาแล้วหลายโปรเจ็ค

    ็History.js

    https://github.com/browserstate/history.js/

  2. OK เยี่ยมเลย

  3. กระจ่างเลยครับ :)

Leave a Reply