กำลังป้อนอินพุตไปยังตัวองค์ประกอบ
นี่เป็นตอนสุดท้ายของบล็อก 4 ตอนใน Chrome มาลองดูกันว่าจะมีการจัดการโค้ดเพื่อแสดงเว็บไซต์อย่างไร ในโพสต์ก่อนหน้านี้ เราได้พูดถึงกระบวนการแสดงผลและได้เรียนรู้เกี่ยวกับตัวจัดวางองค์ประกอบ ในโพสต์นี้ เราจะดูว่า ตัวประกอบทำให้การโต้ตอบราบรื่นเมื่อผู้ใช้ป้อนข้อมูลเข้ามาได้อย่างไร
ป้อนเหตุการณ์จากมุมมองของเบราว์เซอร์
เมื่อคุณได้ยิน "เหตุการณ์การป้อนข้อมูล" คุณอาจนึกถึงการพิมพ์ในช่องข้อความหรือการคลิกเมาส์เท่านั้น แต่จากมุมมองของเบราว์เซอร์ การป้อนข้อมูลหมายถึงท่าทางสัมผัสของผู้ใช้ การเลื่อนด้วยล้อเลื่อนของเมาส์เป็นเหตุการณ์อินพุต และการแตะหรือเมาส์เหนือก็เป็นเหตุการณ์อินพุตเช่นกัน
เมื่อมีการใช้ท่าทางสัมผัสของผู้ใช้ เช่น การแตะหน้าจอ เบราว์เซอร์จะรับท่าทางสัมผัสในตอนแรก อย่างไรก็ตาม กระบวนการของเบราว์เซอร์จะทราบเฉพาะเมื่อท่าทางสัมผัสดังกล่าวเกิดขึ้นเนื่องจากเนื้อหาภายในแท็บได้รับการจัดการโดยกระบวนการแสดงผล ดังนั้นกระบวนการของเบราว์เซอร์จะส่งประเภทเหตุการณ์ (เช่น touchstart
) และพิกัดของเหตุการณ์ไปยังกระบวนการแสดงผล กระบวนการแสดงผลจะจัดการเหตุการณ์อย่างเหมาะสมโดยค้นหาเป้าหมายเหตุการณ์และ Listener เหตุการณ์ที่ทำงานอยู่ที่แนบมา
คอมโพสิตได้รับเหตุการณ์อินพุต
ในโพสต์ก่อนหน้านี้ เราดูว่าตัวทำองค์ประกอบสามารถจัดการการเลื่อนอย่างราบรื่นโดยการประกอบเลเยอร์แบบแรสเตอร์ได้อย่างไร หากไม่ได้แนบ Listener เหตุการณ์อินพุตกับหน้าเว็บ เทรดคอมโพสิตจะสร้างเฟรมผสมใหม่เลยก็ได้โดยไม่เกี่ยวข้องกับเทรดหลัก แต่จะเกิดอะไรขึ้นหากมีผู้ฟัง เหตุการณ์บางเหตุการณ์แนบอยู่กับหน้า เทรดคอมโพสิเตอร์จะทราบได้อย่างไรว่าต้องจัดการเหตุการณ์หรือไม่
ทำความเข้าใจภูมิภาคแบบเลื่อนได้ที่ไม่เร็ว
เนื่องจากการเรียกใช้ JavaScript เป็นงานของเทรดหลัก เมื่อหน้าทำการ Composite เทรดคอมโพสิเตอร์จะทำเครื่องหมายภูมิภาคของหน้าที่มีตัวแฮนเดิลเหตุการณ์แนบเป็น "ภูมิภาคแบบเลื่อนได้แบบไม่เร็ว" เมื่อมีข้อมูลนี้ เทรดคอมโพสเซอร์จะสามารถส่งเหตุการณ์อินพุตไปยังเทรดหลักได้หากมีเหตุการณ์เกิดขึ้นในภูมิภาคนั้น หากเหตุการณ์อินพุตมาจากนอกภูมิภาคนี้ เทรดของตัวคอมโพเนนต์จะทำงานในการจัดเฟรมใหม่โดยไม่ต้องรอเทรดหลัก
ระมัดระวังเมื่อคุณเขียนเครื่องจัดการเหตุการณ์
รูปแบบการจัดการเหตุการณ์ที่พบบ่อยในการพัฒนาเว็บคือการมอบสิทธิ์เหตุการณ์ เนื่องจากลูกโป่งกิจกรรม คุณจึงแนบเครื่องจัดการเหตุการณ์ 1 รายการที่องค์ประกอบด้านบนสุดและมอบสิทธิ์งานตามเป้าหมายเหตุการณ์ได้ คุณอาจเคยเห็นหรือเขียนโค้ดดังตัวอย่างต่อไปนี้
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault();
}
});
เนื่องจากคุณต้องเขียนเครื่องจัดการเหตุการณ์เพียงรายการเดียวสำหรับทุกองค์ประกอบ รูปแบบการมอบสิทธิ์ของกิจกรรมนี้จึงดูน่าสนใจ อย่างไรก็ตาม หากคุณดูโค้ดนี้จากมุมมองของเบราว์เซอร์ ตอนนี้ทั้งหน้าจะมีการทำเครื่องหมายเป็นภูมิภาคที่เลื่อนได้แบบรวดเร็ว ซึ่งหมายความว่าแม้ว่าแอปพลิเคชันจะไม่สนใจอินพุตจากบางส่วนของหน้าเว็บ แต่เทรดคอมโพสิเตอร์จะต้องสื่อสารกับเทรดหลักและรอคอยทุกครั้งที่เหตุการณ์อินพุตเข้ามา ดังนั้น ความสามารถในการเลื่อนอย่างราบรื่นของเครื่องประกอบหน้าเว็บจึงแพ้
คุณสามารถส่งตัวเลือก passive: true
ในตัวฟังเหตุการณ์เพื่อลดปัญหานี้ คำแนะนำนี้สำหรับเบราว์เซอร์ที่คุณยังคงต้องการฟังเหตุการณ์ในเทรดหลัก
แต่เครื่องมือทำองค์ประกอบก็สามารถใส่เฟรมใหม่ได้เลย
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault()
}
}, {passive: true});
ตรวจสอบว่ากิจกรรมยกเลิกได้หรือไม่
ลองนึกภาพว่าคุณมีช่องในหน้าที่ต้องการจำกัดทิศทางการเลื่อนให้เป็นการเลื่อนในแนวนอนเท่านั้น
การใช้ตัวเลือก passive: true
ในเหตุการณ์ตัวชี้จะทำให้การเลื่อนหน้าเว็บเป็นไปอย่างราบรื่น แต่การเลื่อนแนวตั้งอาจเริ่มจากเวลาที่คุณต้องการpreventDefault
เพื่อจำกัดทิศทางการเลื่อน คุณตรวจสอบปัญหานี้ได้โดยใช้เมธอด event.cancelable
document.body.addEventListener('pointermove', event => {
if (event.cancelable) {
event.preventDefault(); // block the native scroll
/*
* do what you want the application to do here
*/
}
}, {passive: true});
หรือคุณอาจใช้กฎ CSS เช่น touch-action
เพื่อกำจัดเครื่องจัดการเหตุการณ์โดยสมบูรณ์
#area {
touch-action: pan-x;
}
หาเป้าหมายของเหตุการณ์
เมื่อเทรดคอมโพสิเตอร์ส่งเหตุการณ์อินพุตไปยังเทรดหลัก สิ่งแรกที่ต้องเรียกใช้คือการทดสอบ Hit เพื่อค้นหาเป้าหมายเหตุการณ์ การทดสอบ Hit ใช้ข้อมูลระเบียนสีที่สร้างขึ้นในกระบวนการแสดงผลเพื่อค้นหาสิ่งที่อยู่ใต้พิกัดจุดซึ่งเหตุการณ์เกิดขึ้น
การลดการส่งเหตุการณ์ไปยังเทรดหลัก
ในโพสต์ก่อนหน้านี้ เราพูดถึงวิธีที่จอแสดงผลทั่วไปรีเฟรชหน้าจอ 60 ครั้งต่อวินาที และดูว่าเราต้องตามจังหวะเพื่อให้ภาพเคลื่อนไหวลื่นไหลได้อย่างไร สำหรับการป้อนข้อมูล อุปกรณ์หน้าจอสัมผัสทั่วไปจะส่งเหตุการณ์การแตะที่ 60-120 ครั้งต่อวินาที และเมาส์ทั่วไปจะส่งเหตุการณ์ 100 ครั้งต่อวินาที เหตุการณ์อินพุตมีความแม่นยำสูงกว่าหน้าจอที่รีเฟรชได้
หากมีการส่งเหตุการณ์ต่อเนื่อง เช่น touchmove
ไปยังเทรดหลัก 120 ครั้งต่อวินาที ก็อาจทำให้มีการทดสอบ Hit และการดำเนินการ JavaScript มากเกินไปเมื่อเทียบกับความช้าของการรีเฟรชหน้าจอ
Chrome จะจัดกลุ่มเหตุการณ์ต่อเนื่อง (เช่น wheel
, mousewheel
, mousemove
, pointermove
, touchmove
) และหน่วงเวลาการส่งโฆษณาจนถึง requestAnimationFrame
ถัดไป เพื่อลดการเรียกใช้เทรดหลักมากเกินไป
ระบบจะส่งเหตุการณ์แยกต่างหากทั้งหมด เช่น keydown
, keyup
, mouseup
, mousedown
, touchstart
และ touchend
ทันที
ใช้ getCoalescedEvents
เพื่อรับเหตุการณ์ภายในเฟรม
สำหรับเว็บแอปพลิเคชันส่วนใหญ่ กิจกรรมที่เป็นเส้นประสานก็น่าจะเพียงพอแล้วให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดี
อย่างไรก็ตาม ถ้าคุณกำลังสร้างสิ่งต่างๆ เช่น แอปพลิเคชันการวาดภาพและวางเส้นทางตามพิกัด touchmove
คุณอาจสูญเสียระหว่างพิกัดในการวาดเส้นเรียบ ในกรณีดังกล่าว คุณสามารถใช้เมธอด getCoalescedEvents
ในเหตุการณ์ตัวชี้เพื่อดูข้อมูลเกี่ยวกับเหตุการณ์ที่รวมเข้าด้วยกันเหล่านั้น
window.addEventListener('pointermove', event => {
const events = event.getCoalescedEvents();
for (let event of events) {
const x = event.pageX;
const y = event.pageY;
// draw a line using x and y coordinates.
}
});
ขั้นตอนถัดไป
ในซีรีส์นี้ เราได้พูดถึงการทำงานภายในของเว็บเบราว์เซอร์ หากคุณไม่เคยนึกถึงเหตุผลที่
เครื่องมือสำหรับนักพัฒนาเว็บแนะนำให้เพิ่ม {passive: true}
ในเครื่องจัดการเหตุการณ์ หรือเหตุผลที่คุณอาจเขียนแอตทริบิวต์ async
ในแท็กสคริปต์ เราหวังว่าซีรีส์นี้จะอธิบายเหตุผลที่เบราว์เซอร์ต้องใช้ข้อมูลเหล่านั้นเพื่อมอบประสบการณ์การใช้งานเว็บที่รวดเร็วและลื่นไหลยิ่งขึ้น
ใช้ Lighthouse
หากคุณต้องการให้โค้ดเหมาะกับเบราว์เซอร์ แต่ไม่รู้ว่าต้องเริ่มต้นตรงไหน Lighthouse คือเครื่องมือที่ให้บริการตรวจสอบเว็บไซต์ต่างๆ และมอบรายงานให้คุณทราบถึงสิ่งที่ดำเนินการได้อย่างถูกต้องและสิ่งที่ควรปรับปรุง นอกจากนี้ การอ่านรายการการตรวจสอบยังช่วยให้คุณเห็นภาพของสิ่งที่เบราว์เซอร์ให้ความสำคัญ
ดูวิธีวัดประสิทธิภาพ
การปรับเปลี่ยนประสิทธิภาพอาจแตกต่างกันไปตามเว็บไซต์ต่างๆ จึงจำเป็นที่คุณจะต้องวัดประสิทธิภาพของเว็บไซต์และตัดสินใจว่าสิ่งใดเหมาะกับเว็บไซต์ของคุณที่สุด ทีมเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome มีบทแนะนำเกี่ยวกับ วิธีวัดประสิทธิภาพเว็บไซต์
เพิ่มนโยบายฟีเจอร์ลงในเว็บไซต์
หากคุณต้องการดำเนินการเพิ่มเติมอีกขั้น นโยบายฟีเจอร์คือฟีเจอร์ใหม่ของแพลตฟอร์มบนเว็บที่อาจเป็นแนวทางให้คุณเมื่อสร้างโปรเจ็กต์ การเปิดนโยบายฟีเจอร์รับประกันลักษณะการทำงานบางอย่างของแอปและป้องกันไม่ให้คุณทำงานผิดพลาด
ตัวอย่างเช่น หากต้องการดูแลไม่ให้แอปบล็อกการแยกวิเคราะห์ ให้เรียกใช้แอปตามนโยบายสคริปต์แบบซิงโครนัส เมื่อเปิดใช้ sync-script: 'none'
ระบบจะป้องกันไม่ให้ JavaScript ที่บล็อกโปรแกรมแยกวิเคราะห์ทำงาน ซึ่งจะป้องกันไม่ให้โค้ดของคุณบล็อกโปรแกรมแยกวิเคราะห์ และเบราว์เซอร์ก็ไม่ต้องกังวลเรื่องการหยุดโปรแกรมแยกวิเคราะห์ชั่วคราว
สรุป
ตอนที่ผมเริ่มสร้างเว็บไซต์ ผมแทบสนใจเฉพาะวิธีเขียนโค้ดและสิ่งที่จะช่วยให้ ผมทำงานได้อย่างมีประสิทธิภาพมากขึ้น เรื่องนี้มีความสำคัญมาก แต่เราก็ควรคำนึงถึงวิธีที่เบราว์เซอร์ นำโค้ดที่เราเขียนไปใช้ด้วย เบราว์เซอร์ที่ทันสมัยได้มีการลงทุนอย่างต่อเนื่องเพื่อช่วยให้ผู้ใช้ได้รับประสบการณ์การใช้งานเว็บที่ดีขึ้น การจัดระเบียบโค้ดของเราอย่างสุภาพต่อเบราว์เซอร์ นำไปสู่การปรับปรุงประสบการณ์ของผู้ใช้ หวังว่าคุณจะร่วมทำภารกิจพิชิตใจเบราว์เซอร์ของเรา
ขอขอบคุณทุกคนที่รีวิวเนื้อหาฉบับร่างช่วงแรกๆ ของซีรีส์นี้ ซึ่งรวมถึง (แต่ไม่จำกัดเพียง Alex Russell, Paul Ireland, Meggin Kearney, Eric Bidelman, Mathias Bynens, Addy Osmani, Kinuko Yasaskie, Kinuko Yasaskie
คุณชอบซีรีส์นี้ไหม หากคุณมีคำถามหรือคำแนะนำสำหรับโพสต์ในอนาคต เรายินดีรับฟังความคิดเห็นจากคุณในส่วนความคิดเห็นด้านล่างหรือ @kosamari บน Twitter