เราเป็นแฟนของ องค์ประกอบที่กำหนดเอง บริเวณนี้. การออกแบบทำให้พวกเขา โดยเฉพาะอย่างยิ่งคล้อยตามการโหลดที่ขี้เกียจซึ่งอาจเป็นประโยชน์ต่อการแสดง
แรงบันดาลใจจาก ของเพื่อนร่วมงาน การทดลอง เมื่อเร็ว ๆ นี้ฉันได้เริ่มเขียนตัวโหลดอัตโนมัติอย่างง่าย: เมื่อใดก็ตามที่องค์ประกอบที่กำหนดเองปรากฏใน DOM เราต้องการโหลดการใช้งานที่เกี่ยวข้องหากยังไม่พร้อมใช้งาน จากนั้นเบราว์เซอร์จะดูแลการอัปเกรดองค์ประกอบดังกล่าวจากที่นั่น
โอกาสที่คุณจะไม่ต้องการทั้งหมดนี้จริงๆ มักจะมีวิธีการที่ง่ายกว่า ใช้อย่างจงใจ เทคนิคที่แสดงที่นี่อาจยังเป็นประโยชน์เพิ่มเติมในชุดเครื่องมือของคุณ
เพื่อความสอดคล้องกัน เราต้องการให้ตัวโหลดอัตโนมัติเป็นองค์ประกอบที่กำหนดเองเช่นกัน ซึ่งหมายความว่าเราสามารถกำหนดค่าได้อย่างง่ายดายผ่าน HTML แต่ก่อนอื่น เรามาระบุองค์ประกอบแบบกำหนดเองที่ไม่ได้รับการแก้ไขเหล่านั้นทีละขั้นตอน:
class AutoLoader extends HTMLElement { connectedCallback() { let scope = this.parentNode; this.discover(scope); }
}
customElements.define("ce-autoloader", AutoLoader);
สมมติว่าเราได้โหลดโมดูลนี้ล่วงหน้า (โดยใช้ async
เหมาะอย่างยิ่ง) เราสามารถทิ้ง <ce-autoloader>
องค์ประกอบใน <body>
ของเอกสารของเรา ซึ่งจะเริ่มกระบวนการค้นหาองค์ประกอบย่อยทั้งหมดของทันที <body>
ซึ่งตอนนี้ถือเป็นองค์ประกอบรากของเรา เราสามารถจำกัดการค้นพบให้อยู่ในทรีย่อยของเอกสารของเราได้โดยการเพิ่ม <ce-autoloader>
ไปยังองค์ประกอบคอนเทนเนอร์ที่เกี่ยวข้องแทน — อันที่จริง เราอาจมีหลายอินสแตนซ์สำหรับแผนผังย่อยที่แตกต่างกัน
แน่นอนว่าเรายังต้องใช้สิ่งนั้น discover
วิธีการ (เป็นส่วนหนึ่งของ AutoLoader
คลาสด้านบน):
discover(scope) { let candidates = [scope, ...scope.querySelectorAll("*")]; for(let el of candidates) { let tag = el.localName; if(tag.includes("-") && !customElements.get(tag)) { this.load(tag); } }
}
ที่นี่เราตรวจสอบองค์ประกอบรูทของเราพร้อมกับลูกหลานทุกคน (*
). หากเป็นองค์ประกอบที่กำหนดเอง — ตามที่ระบุโดยแท็กยัติภังค์ — แต่ยังไม่ได้อัปเกรด เราจะพยายามโหลดคำจำกัดความที่เกี่ยวข้อง การสอบถาม DOM ด้วยวิธีนั้นอาจมีค่าใช้จ่ายสูง ดังนั้นเราควรระมัดระวังเล็กน้อย เราสามารถแบ่งเบาภาระในเธรดหลักได้โดยการชะลองานนี้:
connectedCallback() { let scope = this.parentNode; requestIdleCallback(() => { this.discover(scope); });
}
requestIdleCallback
ยังไม่รองรับในระดับสากล แต่เราสามารถใช้ได้ requestAnimationFrame
เป็นทางเลือก:
let defer = window.requestIdleCallback || requestAnimationFrame; class AutoLoader extends HTMLElement { connectedCallback() { let scope = this.parentNode; defer(() => { this.discover(scope); }); } // ...
}
ตอนนี้เราสามารถดำเนินการต่อเพื่อดำเนินการสิ่งที่ขาดหายไป load
วิธีการฉีดแบบไดนามิก <script>
ธาตุ:
load(tag) { let el = document.createElement("script"); let res = new Promise((resolve, reject) => { el.addEventListener("load", ev => { resolve(null); }); el.addEventListener("error", ev => { reject(new Error("failed to locate custom-element definition")); }); }); el.src = this.elementURL(tag); document.head.appendChild(el); return res;
} elementURL(tag) { return `${this.rootDir}/${tag}.js`;
}
สังเกตการประชุมรหัสตายตัวใน elementURL
. src
URL ของแอตทริบิวต์จะถือว่ามีไดเร็กทอรีที่มีการกำหนดองค์ประกอบแบบกำหนดเองทั้งหมดอยู่ (เช่น <my-widget>
→ /components/my-widget.js
). เราสามารถหากลยุทธ์ที่ซับซ้อนกว่านี้ได้ แต่ก็ดีพอสำหรับจุดประสงค์ของเรา การบังคับ URL นี้ให้แยกจากกันจะทำให้สามารถจัดคลาสย่อยเฉพาะโครงการได้เมื่อจำเป็น:
class FancyLoader extends AutoLoader { elementURL(tag) { // fancy logic }
}
ทั้งสองวิธีโปรดทราบว่าเรากำลังพึ่งพา this.rootDir
. นี่คือที่มาของความสามารถในการกำหนดค่าดังกล่าวมาเพิ่ม getter ที่สอดคล้องกัน:
get rootDir() { let uri = this.getAttribute("root-dir"); if(!uri) { throw new Error("cannot auto-load custom elements: missing `root-dir`"); } if(uri.endsWith("/")) { // remove trailing slash return uri.substring(0, uri.length - 1); } return uri;
}
คุณอาจจะนึกถึง observedAttributes
ตอนนี้ แต่นั่นไม่ได้ช่วยให้อะไรๆ ง่ายขึ้นเลย แถมอัพเดท root-dir
ที่รันไทม์ดูเหมือนเป็นสิ่งที่เราไม่ต้องการ
ตอนนี้ เราสามารถ — และต้อง — กำหนดค่าไดเร็กทอรีองค์ประกอบของเรา: <ce-autoloader root-dir="/components">
.
ด้วยสิ่งนี้ ตัวโหลดอัตโนมัติของเราจึงสามารถทำงานได้ ยกเว้นว่าจะใช้งานได้เพียงครั้งเดียวสำหรับองค์ประกอบที่มีอยู่แล้วเมื่อเริ่มต้นตัวโหลดอัตโนมัติ เราอาจต้องคำนึงถึงองค์ประกอบที่เพิ่มแบบไดนามิกด้วย นั่นคือที่ MutationObserver
เข้ามาเล่น:
connectedCallback() { let scope = this.parentNode; defer(() => { this.discover(scope); }); let observer = this._observer = new MutationObserver(mutations => { for(let { addedNodes } of mutations) { for(let node of addedNodes) { defer(() => { this.discover(node); }); } } }); observer.observe(scope, { subtree: true, childList: true });
} disconnectedCallback() { this._observer.disconnect();
}
ด้วยวิธีนี้ เบราว์เซอร์จะแจ้งให้เราทราบทุกครั้งที่มีองค์ประกอบใหม่ปรากฏขึ้นใน DOM — หรือมากกว่านั้นคือแผนผังย่อยที่เกี่ยวข้อง — ซึ่งเราจะใช้เพื่อเริ่มต้นกระบวนการค้นหาใหม่อีกครั้ง (คุณอาจโต้แย้งว่าเรากำลังประดิษฐ์องค์ประกอบที่กำหนดเองขึ้นใหม่ที่นี่ และคุณน่าจะถูกต้อง)
ตัวโหลดอัตโนมัติของเราทำงานได้อย่างสมบูรณ์แล้ว การปรับปรุงในอนาคตอาจพิจารณาสภาพการแข่งขันที่อาจเกิดขึ้นและตรวจสอบการเพิ่มประสิทธิภาพ แต่โอกาสที่ดีเพียงพอสำหรับสถานการณ์ส่วนใหญ่ แจ้งให้เราทราบในความคิดเห็นหากคุณมีแนวทางอื่น และเราสามารถเปรียบเทียบโน้ตได้!
- เนื้อหาที่ขับเคลื่อนด้วย SEO และการเผยแพร่ประชาสัมพันธ์ รับการขยายวันนี้
- เพลโตบล็อคเชน Web3 Metaverse ข่าวกรอง ขยายความรู้. เข้าถึงได้ที่นี่.
- ที่มา: https://css-tricks.com/an-approach-to-lazy-loading-custom-elements/
- 1
- a
- เกี่ยวกับเรา
- ข้างบน
- ลงชื่อเข้าใช้
- จริง
- ที่เพิ่ม
- นอกจากนี้
- ทั้งหมด
- บรรเทา
- ช่วยให้
- แล้ว
- และ
- เข้าใกล้
- เถียง
- รอบ
- ใช้ได้
- เบราว์เซอร์
- ผู้สมัคร
- ไม่ได้
- ซึ่ง
- ระมัดระวัง
- โอกาส
- ตรวจสอบ
- เด็ก
- ชั้น
- อย่างไร
- ความคิดเห็น
- เปรียบเทียบ
- เงื่อนไข
- ภาชนะ
- การประชุม
- ตรงกัน
- ได้
- หลักสูตร
- ประเพณี
- ออกแบบ
- ต่าง
- การค้นพบ
- เอกสาร
- ไม่
- DOM
- หล่น
- แบบไดนามิก
- ง่ายดาย
- อย่างง่ายดาย
- ทำอย่างละเอียด
- องค์ประกอบ
- พอ
- ความผิดพลาด
- อีเธอร์ (ETH)
- EV
- แม้
- ทุกๆ
- ยกเว้น
- แพง
- ล้มเหลว
- แฟน ๆ
- ชื่อจริง
- ราคาเริ่มต้นที่
- อย่างเต็มที่
- การทำงาน
- อนาคต
- ไป
- ดี
- หัว
- โปรดคลิกที่นี่เพื่ออ่านรายละเอียดเพิ่มเติม
- HTML
- HTTPS
- ในอุดมคติ
- แยกแยะ
- ทันที
- การดำเนินการ
- การดำเนินงาน
- การดำเนินการ
- in
- แทน
- สอบสวน
- IT
- JavaScript
- การสัมภาษณ์
- ชนิด
- ทราบ
- ความยาว
- LIMIT
- น้อย
- โหลด
- โหลด
- ดู
- หลัก
- ทำ
- ทำให้
- วิธี
- วิธี
- อาจ
- หายไป
- โมดูล
- ข้อมูลเพิ่มเติม
- มากที่สุด
- ย้าย
- Mozilla
- หลาย
- จำเป็นต้อง
- จำเป็น
- ใหม่
- ปม
- ส่วนหนึ่ง
- การปฏิบัติ
- เพลโต
- เพลโตดาต้าอินเทลลิเจนซ์
- เพลโตดาต้า
- เล่น
- บวก
- ที่มีศักยภาพ
- อาจ
- กระบวนการ
- วัตถุประสงค์
- เชื่อชาติ
- เมื่อเร็ว ๆ นี้
- เอาออก
- ว่า
- กลับ
- ราก
- สถานการณ์
- ขอบเขต
- ดูเหมือนว่า
- แยก
- ชุด
- น่า
- แสดง
- ง่าย
- เดียว
- So
- บางสิ่งบางอย่าง
- เริ่มต้น
- ขั้นตอน
- ยังคง
- กลยุทธ์
- อย่างเช่น
- ที่สนับสนุน
- TAG
- ใช้เวลา
- เทคนิค
- พื้นที่
- ของพวกเขา
- สิ่ง
- คิด
- ไปยัง
- จริง
- การปรับปรุง
- อัพเกรด
- URI
- URL
- us
- ใช้
- มักจะ
- ผ่านทาง
- ที่
- จะ
- งาน
- โรงงาน
- การเขียน
- ของคุณ
- ลมทะเล