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

โจ เมดเลย์
โจ้ เมดเลย์

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();
    }
  });
});

เบราว์เซอร์จะจัดการการนำทาง เช่น การนำทางจากด้านบนของหน้าไปยัง Anchor (เรียกว่าการย้ายจาก /a ไปยัง /a#id) โดยสมบูรณ์แม้ในแอปหน้าเว็บเดียว แต่การไปยัง Anchor ใน "หน้า" อื่น (/a ไปยัง /b#id) ซึ่งเป็นเรื่องง่ายสำหรับแอปหลายหน้าจะซับซ้อนกว่าสำหรับแอปหน้าเว็บเดียว แอปต้องสกัดกั้นการนำทางไปยัง /b#id โดยใช้ NavigateEvent.transitionWhile() จากนั้นเรียก NavigateEvent.restoreScroll() เพื่อนำแท็ก 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