การเปลี่ยนแปลงของ 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();
    }
  });
});

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