View Transitions
ได้ข้อดีของทั้งสองแบบ
หัวข้อที่มีชื่อว่า “ได้ข้อดีของทั้งสองแบบ”เว็บ multi-page แบบดั้งเดิมจะ reload ทั้ง browser ทุกครั้งที่ navigate — เชื่อถือได้ แต่หน้าจอจะแฟลชขาวและ scroll position รีเซ็ต ส่วน SPA เลี่ยงเรื่องนั้นได้แต่ต้องแลกด้วย JavaScript router ที่หนัก view transitions ของ Astro ให้ความรู้สึกลื่นแบบ SPA บนเว็บ MPA ปกติ ด้วย script แค่ไม่กี่กิโลไบต์
เรา opt in ด้วยการเพิ่ม component เดียวคือ <ClientRouter /> เข้าไปใน <head> ของหน้า — ปกติวางใน layout ที่ใช้ร่วมกันเพื่อให้มีผลทั้งเว็บ:
---import { ClientRouter } from 'astro:transitions';---<html lang="en"> <head> <title>My site</title> <ClientRouter /> </head> <body> <slot /> </body></html>พอมีตัวนี้แล้ว การ navigate ระหว่างหน้าในเว็บของเราจะถูก intercept และจัดการฝั่ง client: Astro fetch หน้าถัดไป, swap content เข้ามา และ animate การเปลี่ยน — ไม่มี full reload browser ที่ไม่รองรับ API เบื้องหลังจะ fallback ไปเป็น navigation ปกติ ทุกอย่างจึงไม่พัง
navigation ทำงานยังไง
หัวข้อที่มีชื่อว่า “navigation ทำงานยังไง”flowchart LR click["User clicks a link"] --> intercept["ClientRouter intercepts (no full reload)"] intercept --> fetch["Fetch the next page HTML"] fetch --> swap["Swap in the new content, animate"] swap --> event["Fire astro:page-load"]
Transition directives
หัวข้อที่มีชื่อว่า “Transition directives”โดย default Astro จะ cross-fade หน้า เราคุม animation ต่อ element ได้ด้วย directive:
transition:name— ตั้งชื่อเดียวกันให้ element บนทั้งสองหน้า เพื่อให้ Astro morph จากอันหนึ่งไปอีกอัน (shared-element transition เช่น thumbnail ที่ค่อย ๆ ขยายเป็น hero image)transition:animate— เลือก animation (fade,slideหรือแบบ custom) import helper จากastro:transitionstransition:persist— เก็บ DOM และ state ของ component ไว้ข้าม navigation แทนที่จะ re-render เหมาะกับ video ที่กำลังเล่นหรือ audio player ที่ไม่ควรเริ่มใหม่
---import { slide } from 'astro:transitions';---<!-- This heading slides between pages; the player keeps playing across nav. --><h1 transition:name="page-title" transition:animate={slide({ duration: 200 })}>Title</h1><video controls autoplay transition:name="player" transition:persist />Lifecycle events
หัวข้อที่มีชื่อว่า “Lifecycle events”เพราะ navigation ไม่ trigger full page load อีกต่อไป script ที่รันตอน DOMContentLoaded จะไม่รันซ้ำตอน navigate แบบ client-side Astro จึง fire event ของตัวเองให้เรา re-initialize:
astro:page-load— fire หลังทุก navigation (ทั้ง load ครั้งแรก และ การ swap แบบ client-side) วาง initialization ไว้ตรงนี้แทนDOMContentLoadedastro:after-swap— fire ทันทีหลัง DOM ใหม่ถูก swap เข้ามา ก่อน paint (เหมาะกับการ restore theme/state เพื่อเลี่ยงการแฟลช)
document.addEventListener('astro:page-load', () => { // runs on first load AND after every client-side navigation initAnalytics();});นี่คือ gotcha ที่พบบ่อยที่สุดของ view transitions: init script ที่ทำงานตอน load ครั้งแรกแต่ “หยุดทำงาน” หลัง navigate เพราะผูกกับ DOMContentLoaded ให้ย้ายไปที่ astro:page-load