อินพุตกำลังมายังคอมโพสิต
นี่เป็นบล็อกสุดท้ายของ 4 ตอนในหัวข้อเกี่ยวกับ Chrome ตรวจสอบวิธีจัดการ โค้ดของเราเพื่อแสดงเว็บไซต์ ในโพสต์ก่อนหน้า เราได้ดูกระบวนการแสดงผลและเรียนรู้เกี่ยวกับเครื่องมือจัดวางองค์ประกอบ ในโพสต์นี้ เราจะ ดูว่าเครื่องมือประกอบช่วยให้การโต้ตอบที่ราบรื่นเมื่อมีข้อมูลจากผู้ใช้เข้ามาได้อย่างไร
ป้อนเหตุการณ์จากมุมมองของเบราว์เซอร์
เมื่อได้ยิน "ป้อนข้อมูลเหตุการณ์" คุณอาจนึกถึงการพิมพ์ในช่องข้อความหรือการคลิกเมาส์ แต่จาก มุมมองของเบราว์เซอร์ การป้อนข้อมูล หมายถึงท่าทางสัมผัสใดๆ จากผู้ใช้ การเลื่อนล้อเลื่อนของเมาส์เป็นอินพุต เหตุการณ์ และการแตะ หรือวางเมาส์เหนือ ก็เป็นเหตุการณ์อินพุตด้วย
เมื่อมีท่าทางสัมผัสของผู้ใช้ เช่น การแตะบนหน้าจอ กระบวนการของเบราว์เซอร์จะเป็นการดำเนินการที่จะได้รับ
ด้วยท่าทางสัมผัสในตอนแรก อย่างไรก็ตาม กระบวนการของเบราว์เซอร์จะทราบเฉพาะตำแหน่งที่เกิดท่าทางสัมผัสดังกล่าวนับตั้งแต่นั้น
เนื้อหาที่อยู่ในแท็บจะได้รับการจัดการโดยกระบวนการของโหมดแสดงภาพ ดังนั้นกระบวนการของเบราว์เซอร์จะส่งเหตุการณ์
(เช่น touchstart
) และพิกัดไปยังกระบวนการของโหมดแสดงภาพ กระบวนการแสดงผลจะจัดการ
เหตุการณ์อย่างเหมาะสมโดยค้นหาเป้าหมายเหตุการณ์และเรียกใช้ Listener เหตุการณ์ที่แนบอยู่
![เหตุการณ์อินพุต](https://developer.chrome.google.cn/static/blog/inside-browser-part4/image/input-event-265a73164e715.png?authuser=5&hl=th)
คอมโพสิเตอร์รับเหตุการณ์อินพุต
ในโพสต์ก่อนหน้านี้ เราได้ดูวิธีที่คอมโพสิตจะจัดการกับการเลื่อนอย่างราบรื่นด้วยการจัดวางองค์ประกอบ เลเยอร์ที่แรสเตอร์ หากไม่มี Listener เหตุการณ์อินพุตแนบกับหน้าเว็บ เทรดแบบผสมจะทำสิ่งต่อไปนี้ได้ สร้างเฟรมผสมใหม่โดยเป็นอิสระจากเทรดหลัก แล้วจะเกิดอะไรขึ้นหากบางเหตุการณ์ ได้แนบผู้ฟังมาอยู่ในหน้าไหม เทรดคอมโพสิตจะรู้ได้อย่างไรว่าเหตุการณ์นั้นต้องการ ที่ต้องจัดการไหม
การทำความเข้าใจภูมิภาคที่เลื่อนได้ที่ไม่เร็ว
เนื่องจากการเรียกใช้ JavaScript เป็นงานของเทรดหลัก เมื่อมีการรวมหน้าเว็บ เทรดคอมโพสิต ทำเครื่องหมายภูมิภาคของหน้าเว็บที่มีเครื่องจัดการเหตุการณ์แนบอยู่ว่า "ภูมิภาคที่เลื่อนไม่ได้อย่างรวดเร็ว" โดย เมื่อมีข้อมูลนี้ เทรดคอมโพสิตจะส่งเหตุการณ์อินพุตไปยังเทรดหลักได้ หากเกิดเหตุการณ์ขึ้นในภูมิภาคนั้น หากเหตุการณ์การป้อนข้อมูลมาจากนอกภูมิภาคนี้ เทรดคอมโพสิตจะดำเนินการขณะทำการประกอบเฟรมใหม่โดยไม่ต้องรอเทรดหลัก
![ภูมิภาคที่เลื่อนได้แบบจำกัดและเลื่อนไม่ได้](https://developer.chrome.google.cn/static/blog/inside-browser-part4/image/limited-non-fast-scrollab-376be5ee2cd6b.png?authuser=5&hl=th)
ระมัดระวังเมื่อเขียนเครื่องจัดการเหตุการณ์
รูปแบบการจัดการเหตุการณ์ทั่วไปในการพัฒนาเว็บคือการมอบสิทธิ์เหตุการณ์ เนื่องจากลูกโป่งกิจกรรม แนบเครื่องจัดการเหตุการณ์ที่องค์ประกอบบนสุดและมอบหมายงานตามเป้าหมายเหตุการณ์ได้ คุณ อาจเห็นหรือได้เขียนโค้ดไว้ดังเช่นด้านล่างนี้
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault();
}
});
เนื่องจากคุณต้องเขียนเครื่องจัดการเหตุการณ์เพียง 1 รายการสำหรับองค์ประกอบทั้งหมด การยศาสตร์ของเหตุการณ์นี้ รูปแบบการมอบสิทธิ์นั้นน่าสนใจ อย่างไรก็ตาม หากคุณดูโค้ดนี้จากจุดของเบราว์เซอร์ ตอนนี้หน้าทั้งหน้าจะถูกทำเครื่องหมายว่าเลื่อนไปอย่างไม่เร็ว ซึ่งหมายความว่าแม้ว่า ไม่สนใจอินพุตจากบางส่วนของหน้าเว็บ ชุดข้อความของคอมโพสิตจึงมีหน้าที่ สื่อสารกับเทรดหลัก และรอทุกครั้งที่มีเหตุการณ์อินพุตเข้ามา ดังนั้น ความสามารถในการเลื่อนที่ราบรื่นของคอมโพสิเตอร์จะแพ้
![ภูมิภาคที่เลื่อนได้แบบเต็มหน้า](https://developer.chrome.google.cn/static/blog/inside-browser-part4/image/full-page-non-fast-scroll-dd3010cc3ee0f.png?authuser=5&hl=th)
โปรดส่ง passive: true
ตัวเลือกในกิจกรรมเพื่อลดปัญหานี้
Listener คําแนะนํานี้สําหรับเบราว์เซอร์ที่คุณยังต้องการฟังเหตุการณ์ในชุดข้อความหลัก
แต่เครื่องมือทำ Compose จะสามารถทำการรวมเฟรมใหม่ได้เช่นกัน
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault()
}
}, {passive: true});
ตรวจสอบว่ากิจกรรมยกเลิกได้หรือไม่
![การเลื่อนหน้า](https://developer.chrome.google.cn/static/blog/inside-browser-part4/image/page-scroll-2cf8d804f8587.png?authuser=5&hl=th)
ลองนึกภาพว่าคุณมีช่องในหน้าที่ต้องการจำกัดทิศทางการเลื่อนเป็นการเลื่อนในแนวนอนเท่านั้น
การใช้ตัวเลือก 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](https://developer.chrome.google.cn/static/blog/inside-browser-part4/image/hit-test-39f1d20855064.png?authuser=5&hl=th)
เมื่อเทรดคอมโพสิตส่งเหตุการณ์อินพุตไปยังเทรดหลัก สิ่งแรกที่จะทำงานคือ Hit ทดสอบเพื่อหาเป้าหมายเหตุการณ์ การทดสอบ Hit ใช้ข้อมูลบันทึกการแสดงผลที่สร้างขึ้นในการแสดงภาพ เพื่อค้นหาสิ่งที่อยู่ใต้พิกัดจุดซึ่งเกิดเหตุการณ์ขึ้น
การลดการส่งเหตุการณ์ไปยังเทรดหลัก
ในโพสต์ก่อนหน้า เราได้พูดถึงวิธีที่จอแสดงผลตามปกติของเรารีเฟรชหน้าจอ 60 ครั้งต่อวินาที เราจำเป็นต้องใช้จังหวะที่สม่ำเสมอ ในการสร้างภาพเคลื่อนไหวที่ลื่นไหล หน้าจอสัมผัสโดยทั่วไป อุปกรณ์จะส่งเหตุการณ์การสัมผัส 60-120 ครั้งต่อวินาที และเมาส์ทั่วไปจะส่งเหตุการณ์ 100 ครั้ง อย่างที่สอง เหตุการณ์อินพุตมีความละเอียดสูงกว่าหน้าจอที่รีเฟรชได้
หากมีการส่งเหตุการณ์ต่อเนื่อง เช่น touchmove
ไปยังเทรดหลัก 120 ครั้งต่อวินาที
อาจทริกเกอร์การทดสอบ Hit และการเรียกใช้ JavaScript มากเกินไปเมื่อเทียบกับความช้า
หน้าจอก็รีเฟรชได้
![เหตุการณ์ที่ไม่กรอง](https://developer.chrome.google.cn/static/blog/inside-browser-part4/image/unfiltered-events-5c569da8f6466.png?authuser=5&hl=th)
ในการลดการเรียกไปยังเทรดหลักมากเกินไป Chrome จะรวมเหตุการณ์ต่อเนื่อง (เช่น
wheel
, mousewheel
, mousemove
, pointermove
, touchmove
) และล่าช้าการจัดส่งไปจนถึง
ก่อนถึงrequestAnimationFrame
ถัดไป
![เหตุการณ์แบบรวม](https://developer.chrome.google.cn/static/blog/inside-browser-part4/image/coalesced-events-42fbb3813612d.png?authuser=5&hl=th)
เหตุการณ์ที่ไม่ต่อเนื่อง เช่น keydown
, keyup
, mouseup
, mousedown
, touchstart
และ touchend
จะมีการจัดส่งทันที
ใช้ getCoalescedEvents
เพื่อรับเหตุการณ์ภายในเฟรม
สำหรับเว็บแอปพลิเคชันส่วนใหญ่ กิจกรรมที่สัมพันธ์กันควรเพียงพอที่จะให้ประสบการณ์ที่ดีแก่ผู้ใช้
แต่ถ้าคุณกำลังสร้างสิ่งต่างๆ เช่น แอปพลิเคชันการวาดภาพและวางเส้นทางตาม
touchmove
คุณอาจสูญเสียพิกัดระหว่างพิกัดเพื่อให้วาดเส้นได้อย่างราบรื่น ในกรณีดังกล่าว
คุณสามารถใช้เมธอด getCoalescedEvents
ในเหตุการณ์ตัวชี้เพื่อดูข้อมูลเกี่ยวกับสิ่งต่างๆ เหล่านั้น
ที่สัมพันธ์กัน
![getCoalescedEvents](https://developer.chrome.google.cn/static/blog/inside-browser-part4/image/getcoalescedevents-ab59c1cb92e1b.png?authuser=5&hl=th)
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 DevTools มีบทแนะนำเกี่ยวกับ วิธีวัดประสิทธิภาพของเว็บไซต์
เพิ่มนโยบายฟีเจอร์ในเว็บไซต์ของคุณ
หากคุณต้องการเพิ่มขั้นตอน นโยบายฟีเจอร์
ฟีเจอร์แพลตฟอร์มเว็บที่เป็นเหมือนการป้องกันคุณเมื่อคุณสร้างโครงการ กำลังเปิด
นโยบายฟีเจอร์รับประกันลักษณะการทำงานบางอย่างของแอปและป้องกันไม่ให้คุณทำงานผิดพลาด
เช่น หากต้องการแน่ใจว่าแอปจะไม่บล็อกการแยกวิเคราะห์ คุณเรียกใช้แอปได้ใน
ของนโยบายสคริปต์แบบซิงโครนัส เมื่อเปิดใช้ sync-script: 'none'
แล้ว JavaScript ที่บล็อกโปรแกรมแยกวิเคราะห์จะ
ไม่ให้มีการดำเนินการ วิธีนี้จะช่วยป้องกันไม่ให้โค้ดของคุณบล็อกโปรแกรมแยกวิเคราะห์และ
ไม่จำเป็นต้องกังวลเกี่ยวกับการหยุดโปรแกรมแยกวิเคราะห์ชั่วคราว
สรุป
![ขอบคุณ](https://developer.chrome.google.cn/static/blog/inside-browser-part4/image/thank-you-cae9a20f3c237.png?authuser=5&hl=th)
พอเริ่มสร้างเว็บไซต์ ฉันแทบจะสนใจแค่วิธีเขียนโค้ดและ จะช่วยให้ผมทำงานได้อย่างมีประสิทธิภาพมากขึ้น เรื่องพวกนั้นสำคัญ แต่เราควรคำนึงถึงวิธี จะใช้โค้ดที่เราเขียน เบราว์เซอร์ที่ทันสมัยได้ลงทุนอย่างต่อเนื่องเพื่อพัฒนาวิธี เพื่อมอบประสบการณ์เว็บที่ดียิ่งขึ้นให้แก่ผู้ใช้ การทำให้เบราว์เซอร์ปลอดภัยด้วยการจัดระเบียบโค้ดของเรา ก็จะทำให้ประสบการณ์ของผู้ใช้ดีขึ้นด้วย ฉันหวังว่าคุณจะเข้าร่วมภารกิจเพื่อทำความดีให้แก่เบราว์เซอร์ของฉันกับฉัน!
ขอขอบคุณเป็นอย่างสูงสำหรับทุกคนที่ตรวจสอบฉบับร่างช่วงแรกของชุดหนังสือนี้ ซึ่งรวมถึง (แต่ไม่จำกัดเพียง) ถึง): Alex Russell Paul Ireland Meggin Kearney Eric Bidelman Mathias Bynens Addy Osmani Kinuko Yasuda Nasko Oskov และ Charlie Reis
คุณชอบซีรีส์นี้ไหม หากคุณมีคำถามหรือคำแนะนำสำหรับโพสต์ในอนาคต ฉันอยากฟังความเห็นจากคุณในส่วนความคิดเห็นด้านล่างหรือ @kosamari ใน Twitter