การเปลี่ยนแปลงของ NavigationEvent ใน Chrome 105

Joe Medley
Joe Medley

Chrome 105 เปิดตัวเมธอดใหม่ 2 รายการใน NavigateEvent ของ Navigation API (เปิดตัวใน 102) เพื่อปรับปรุงเมธอดที่พิสูจน์แล้วว่ามีปัญหาในทางปฏิบัติ intercept() ซึ่งช่วยให้นักพัฒนาแอปควบคุมสถานะหลังจากการนําทางได้ จะเข้ามาแทนที่ transitionWhile() ซึ่งใช้งานยาก เมธอด scroll() ซึ่งเลื่อนไปยังแท็ก Anchor ที่ระบุไว้ใน URL จะแทนที่ restoreScroll() ซึ่งใช้ไม่ได้กับการนำทางทุกประเภท

บทความนี้จะอธิบายปัญหาของทั้ง 2 วิธีและวิธีที่วิธีการใหม่แก้ไขปัญหาเหล่านั้น

เมธอด NavigateEvent.trasitionWhile() ซึ่งเปิดตัวพร้อมกับ Navigation API ใน Chrome 102 จะขัดจังหวะการไปยังส่วนต่างๆ สำหรับการเปลี่ยนไปใช้ฝั่งไคลเอ็นต์ในแอปแบบหน้าเดียว โดยอาร์กิวเมนต์แรกคือสัญญาที่จะส่งสัญญาณไปยังเบราว์เซอร์และส่วนอื่นๆ ของเว็บแอปพลิเคชันว่าเสร็จแล้ว

การดำเนินการนี้ใช้ไม่ได้จริง ลองพิจารณารูปแบบการเขียนโค้ดทั่วไปนี้

event.transitionWhile((async () => {
  doSyncStuff();
  await doAsyncStuff();
})());

ซึ่งเทียบเท่ากับโค้ดด้านล่าง ซึ่งทําให้การนำทางบางส่วนทํางานก่อนที่ API จะทราบว่านักพัฒนาแอปตั้งใจที่จะขัดขวางการนำทาง

doSyncStuff();
event.transitionWhile((async () => {
  await doAsyncStuff();
})());

ตัวอย่างหนึ่งที่ทำให้แอปสับสนคือในลอจิกการกู้คืนการเลื่อนที่แอปจะบันทึกตำแหน่งที่เลื่อนหลังการเปลี่ยนแปลง DOM ไม่ใช่ก่อนหน้า

มีอะไรเปลี่ยนแปลงบ้าง

ข้อมูลจำเพาะปัจจุบันได้แนะนำ NavigateEvent.intercept() มาใช้แทน transitionWhile() เมธอดใหม่จะใช้ตัวแฮนเดิลนอกเหนือจากพร็อพเพอร์ตี้ focusReset และ scrollRestoration ที่ transitionWhile() รองรับ ตัวแฮนเดิลใหม่จะทำงานเสมอหลังจากที่คอมมิตการนำทางแล้ว และสิ่งต่างๆ เช่น มีการจับภาพตำแหน่งการเลื่อนแล้ว เพื่อหลีกเลี่ยงไม่ให้เกิดปัญหากับ transitionWhile()

วิธีการ transitionWhile() ยังใช้งานได้อยู่ แต่เลิกใช้งานแล้วและจะถูกนำออกใน Chrome 108

การใช้ intercept()

NavigateEvent.intercept() มีข้อจํากัดเหมือนกับ transitionWhile() กล่าวคือเรียกใช้ไม่ได้ในเหตุการณ์การนําทางบางรายการ ไม่สามารถสกัดกั้นการไปยังส่วนต่างๆ ในแหล่งที่มาต่างๆ และไม่สามารถสกัดกั้นการไปยังส่วนต่างๆ ในเอกสารต่างๆ ซึ่งจะทำให้เกิด DOMException ประเภท "SecurityError"

หากต้องการใช้ intercept() ให้ส่งตัวแฮนเดิลที่กําหนดเองเมื่อเรียกใช้

navigation.addEventListener("navigate", event => {
  event.intercept({
    async handler() {
      doSyncStuff();
      await doAsyncStuff();
    }
  });
});

การนำทาง เช่น การนำทางจากด้านบนของหน้าไปยังจุดยึด (เรียกการย้ายจาก /a ไปยัง /a#id) นั้นจัดการโดยเบราว์เซอร์โดยสมบูรณ์แม้ในแอปแบบหน้าเดียว แต่การนำทางไปยังจุดยึดใน "หน้า" อื่น (/a ไปยัง /b#id) ซึ่งง่ายสำหรับแอปแบบหลายหน้าจะซับซ้อนกว่าสำหรับแอปแบบหน้าเดียว แอปต้องขัดจังหวะการนำทางไปยัง /b#id โดยใช้ NavigateEvent.transitionWhile() จากนั้นเรียกใช้ NavigateEvent.restoreScroll() เพื่อแสดงโฆษณา Anchor ดังที่กล่าวไว้ข้างต้น การดำเนินการนี้ยังทำได้ยากในขณะนี้

มีอะไรเปลี่ยนแปลงบ้าง

ในแอปที่มีหน้าเดียว ตอนนี้คุณควบคุมได้ว่าจะให้เบราว์เซอร์จัดการการเลื่อนไปยังแท็ก Anchor หรือให้โค้ดทำงานหรือไม่

การใช้ scroll()

โดยค่าเริ่มต้น เบราว์เซอร์จะพยายามจัดการการเลื่อนโดยอัตโนมัติเมื่อแฮนเดิลการขัดจังหวะทำงาน หากต้องการจัดการการเลื่อนด้วยตนเอง ให้ตั้งค่า scroll เป็น "manual" แล้วเรียกใช้ NavigateEvent.scroll() เมื่อเบราว์เซอร์ควรพยายามตั้งค่าตำแหน่งการเลื่อน

navigation.addEventListener("manual", event => {
  scroll: "manual",
  event.intercept({
    async handler() {
      doSyncStuff();
      // Handle scrolling earlier than by default:
      event.scroll();
      await doAsyncStuff();
    }
  });
});

วิธี restoreScroll() ยังใช้งานได้อยู่ แต่เลิกใช้งานแล้วและจะถูกนำออกใน Chrome 108

บทสรุป

เราหวังว่าจะอัปเดตบทความเกี่ยวกับ Navigation API ในเร็วๆ นี้ ในระหว่างนี้ ข้อกำหนดของ API นี้มีข้อมูลมากมายสำหรับนักพัฒนาเว็บโดยเฉพาะ

รูปภาพโดย Tim Gouw ใน Unsplash