आंतरिक बटन के click को हैंडल करें, फिर कंपोनेंट होस्ट से एक नामित CustomEvent डिस्पैच करें। इसका उपयोग करने वाला पेज उस होस्ट पर सुनता है और event.detail पढ़ता है। यह गाइड Mac पर एक पूरा स्थानीय ब्राउज़र डेमो बनाती है और बताती है कि हर लिसनर को किन इवेंट विकल्पों की ज़रूरत है।
उपभोक्ता को चाहिए ऐसी सूचना परिभाषित करें
सादे JavaScript वेब कंपोनेंट में, उपभोक्ता वह पेज या बाहरी कंपोनेंट होता है जो आपके कस्टम एलिमेंट का उपयोग करता है। यहाँ ठोस काम यह है कि आंतरिक बटन सक्रिय होने पर उपभोक्ता प्रतिक्रिया दे सके, और उसे कंपोनेंट के shadow DOM से पूछताछ न करनी पड़े।
उदाहरण में Tile A लेबल वाली एक कृत्रिम टाइल का उपयोग किया गया है। इसका सार्वजनिक इवेंट tile-activate है, जिसमें एक itemId और सक्रियण count होता है। CustomEvent इस एप्लिकेशन डेटा के लिए detail फ़ील्ड देता है; इवेंट का नाम केस-संवेदी होता है। डिस्पैच करने वाले कोड और लिसनर, दोनों को ठीक एक ही नाम का उपयोग करना चाहिए। CustomEvent कंस्ट्रक्टर का दस्तावेज़।
इन विकल्पों को एक छोटे इंटरफ़ेस अनुबंध की तरह देखें:
- नाम:
tile-activate। - अर्थ: आंतरिक बटन सक्रिय किया गया है और गिनती अपडेट हुई है।
- पेलोड:
detail.itemIdटाइल की पहचान करता है;detail.countमें इसकी अपडेट की गई गिनती होती है। - उत्पत्ति: कस्टम एलिमेंट होस्ट सूचना डिस्पैच करता है।
- डिलीवरी: सीधे उपभोक्ता और पूर्वज लिसनर इसे प्राप्त कर सकते हैं, जिसमें बाहरी shadow सीमाओं के पार भी शामिल है।
ये इस उदाहरण के लिए डिज़ाइन विकल्प हैं। उपयोगी इवेंट उस कार्रवाई का वर्णन करता है जिसकी उपभोक्ता को परवाह है। इससे कंपोनेंट अपना आंतरिक मार्कअप बाद में बदल सकता है और सूचना इंटरफ़ेस वही रख सकता है।
अपने Mac पर पूरा उदाहरण बनाएँ और खोलें
आपको किसी मौजूदा डेस्कटॉप ब्राउज़र और सादे टेक्स्ट एडिटर की ज़रूरत है। इस एकल-फ़ाइल उदाहरण के लिए पैकेज इंस्टॉल करने या बिल्ड चरण की आवश्यकता नहीं है। इसमें HTMLElement को विस्तारित करने वाला एक स्वायत्त कस्टम एलिमेंट है। यह प्लेटफ़ॉर्म पैटर्न HTML Standard के कस्टम एलिमेंट अनुभाग में दर्ज है।
TextEdit में File > New चुनें, फिर Format > Make Plain Text चुनें। नीचे दिया पूरा दस्तावेज़ पेस्ट करें। File > Save चुनें, फ़ाइल का नाम component-click.html रखें और संकेत मिलने पर Use .html चुनें। ये TextEdit में HTML फ़ाइल बनाने के Apple के दस्तावेज़ीकृत चरण हैं। Mac पर TextEdit में HTML दस्तावेज़ों के साथ काम करें।
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Component click notification</title>
</head>
<body>
<h1>Component click notification</h1>
<section id="demo">
<action-tile id="tile" item-id="tile-a"></action-tile>
<p id="direct-status">Direct listener: waiting</p>
<p id="parent-status">Parent listener: waiting</p>
</section>
<script>
class ActionTile extends HTMLElement {
constructor() {
super();
this._count = 0;
this._button = null;
this._root = this.attachShadow({ mode: "open" });
this._handleClick = () => {
this._count += 1;
this.dispatchEvent(new CustomEvent("tile-activate", {
detail: {
itemId: this.getAttribute("item-id"),
count: this._count
},
bubbles: true,
composed: true
}));
};
}
connectedCallback() {
if (!this._button) {
this._button = document.createElement("button");
this._button.type = "button";
this._button.textContent = "Activate Tile A";
this._root.append(this._button);
}
this._button.addEventListener("click", this._handleClick);
}
disconnectedCallback() {
this._button.removeEventListener("click", this._handleClick);
}
}
customElements.define("action-tile", ActionTile);
const tile = document.getElementById("tile");
const demo = document.getElementById("demo");
const directStatus = document.getElementById("direct-status");
const parentStatus = document.getElementById("parent-status");
tile.addEventListener("tile-activate", (event) => {
const { itemId, count } = event.detail;
directStatus.textContent =
`Direct listener: ${itemId}, activation ${count}`;
});
demo.addEventListener("tile-activate", (event) => {
const { itemId, count } = event.detail;
parentStatus.textContent =
`Parent listener: ${itemId}, activation ${count}`;
});
</script>
</body>
</html>
सेव की गई फ़ाइल अपने ब्राउज़र में खोलें और Activate Tile A पर क्लिक करें। पहला अपेक्षित परिणाम Direct listener: tile-a, activation 1 और Parent listener: tile-a, activation 1 है। हर अगली सक्रियता पर दोनों दिखाई गई गिनतियाँ एक-एक बढ़ती हैं। ये उदाहरण के अपेक्षित परिणाम हैं, ब्राउज़र में किए गए परीक्षण के नतीजों की रिपोर्ट नहीं।
कोड में मुख्य क्रम साफ़ दिखता है: कंपोनेंट की स्थिति अपडेट करें, सूचना बनाएँ, उसे this से डिस्पैच करें, और उपभोक्ता को अपना इंटरफ़ेस अपडेट करने दें। dispatchEvent() लागू लिसनर को लौटने से पहले सिंक्रोनस रूप से चलाता है, इसलिए उपभोक्ताओं को अपने हैंडलर के दौरान अपडेट की गई गिनती दिखती है। dispatchEvent का दस्तावेज़।
सही bubbling और shadow सीमा विकल्प चुनें
डिस्पैच का लक्ष्य और लिसनर की जगह तय करते हैं कि कौन से विकल्प मायने रखते हैं। होस्ट पर सीधे लगाया गया लिसनर, उस होस्ट पर डिस्पैच किया गया इवेंट प्राप्त करता है, भले ही bubbles false हो। सामान्य पूर्वज लिसनर को bubbling की ज़रूरत होती है। Shadow सीमा पार करने के लिए composed भी आवश्यक है। bubbles, composed, और cancelable के मूल डिफ़ॉल्ट, तीनों false हैं। DOM Standard: Event इंटरफ़ेस।
यह निर्णय तालिका, प्रसार के उन नियमों से निकाली गई है। इसमें माना गया है कि सामान्य लिसनर capture के बिना रजिस्टर किए गए हैं और कोई हैंडलर प्रसार को नहीं रोकता।
| कस्टम इवेंट कहाँ शुरू होता है | उपभोक्ता कहाँ सुनता है | उस मार्ग के लिए कॉन्फ़िगरेशन |
|---|---|---|
| कंपोनेंट होस्ट | वही होस्ट | दोनों में से किसी फ़्लैग को true करने की ज़रूरत नहीं |
| कंपोनेंट होस्ट | उसी ट्री में सामान्य पूर्वज | bubbles: true |
| आंतरिक shadow बटन | उस shadow root के बाहर सामान्य पूर्वज | bubbles: true, composed: true |
| किसी दूसरे shadow tree के भीतर कंपोनेंट होस्ट | उस बाहरी shadow root के बाहर सामान्य पूर्वज | bubbles: true, composed: true |
डेमो में this.dispatchEvent(...) होस्ट पर सूचना शुरू करता है। इसलिए इसे कंपोनेंट के अपने shadow root से बाहर निकलने की ज़रूरत नहीं है। अगर इस टाइल को बाद में किसी बाहरी कंपोनेंट के भीतर रखा जाए, तो composed: true सूचना को उसकी shadow सीमा के पार इस्तेमाल करने योग्य बनाता है। इतनी व्यापक पहुँच सार्वजनिक इंटरफ़ेस का सोच-समझकर तय किया गया हिस्सा होनी चाहिए। Event composed का दस्तावेज़।
केंद्रित प्रयोग के लिए, केवल bubbles: true को bubbles: false में बदलें, सेव करें और पेज फिर से लोड करें। सक्रिय करने पर सीधे लिसनर की स्थिति अपडेट होनी चाहिए, जबकि पैरेंट की स्थिति Parent listener: waiting ही रहेगी। उसके बाद bubbling को पहले जैसा कर दें। केवल composed को false करने पर इस खास दस्तावेज़ में दोनों लिसनर काम करते रहेंगे, क्योंकि दोनों में से कोई भी मार्ग shadow सीमा पार नहीं करता।
आरंभीकरण और दोबारा जुड़ने के व्यवहार को बनाए रखें
शुरू में इवेंट डिलीवरी सही दिख सकती है, फिर भी कंपोनेंट को कहीं ले जाने या दोबारा जोड़ने पर सूचनाएँ दोहराई जा सकती हैं। निर्माण, कनेक्शन और सफ़ाई की ज़िम्मेदारियाँ स्पष्ट रखें।
कंस्ट्रक्टर सबसे पहले super() को कॉल करता है, फिर स्थिति आरंभ करता है और shadow root जोड़ता है। रेंडरिंग connectedCallback() में होती है और मौजूदा बटन रेफ़रेंस के ज़रिए इसे एक बार चलने तक सीमित किया गया है। ये विकल्प HTML Standard की कंस्ट्रक्टर संबंधी आवश्यकताओं और उस मार्गदर्शन के अनुरूप हैं जिसमें कनेक्शन कॉलबैक दोबारा चलने पर न दोहराए जाने वाले आरंभीकरण को सुरक्षित रखने की सलाह दी गई है। कस्टम एलिमेंट कंस्ट्रक्टर और प्रतिक्रियाओं की आवश्यकताएँ।
कंपोनेंट कनेक्ट होने पर अपना आंतरिक क्लिक लिसनर रजिस्टर करता है और डिस्कनेक्ट होने पर उसे हटाता है। दोबारा कनेक्ट होने पर, यह मौजूदा बटन का फिर से उपयोग करता है और _count को बनाए रखता है। कनेक्शन और डिस्कनेक्शन कॉलबैक जीवनचक्र हुक हैं, जिन्हें एलिमेंट के दस्तावेज़ में आने-जाने पर कॉल किया जाता है। कस्टम एलिमेंट का उपयोग।
संग्रहित _handleClick फ़ंक्शन मायने रखता है: हटाते समय उसी फ़ंक्शन की पहचान होनी चाहिए जिसका उपयोग रजिस्ट्रेशन में किया गया था, और capture सेटिंग भी वही होनी चाहिए। हटाने की कॉल में एक नया arrow function बनाने से रजिस्टर किए गए लिसनर की पहचान नहीं होगी। removeEventListener का दस्तावेज़।
अगर किसी बड़े कंपोनेंट में आप window, document, या किसी अन्य बाहरी लक्ष्य पर लिसनर जोड़ते हैं, तो उनके लिए भी उतनी ही स्पष्ट सफ़ाई करें। जीवनचक्र में होने वाले बदलावों को सूचना के अर्थ से अलग रखें, ताकि एलिमेंट के दोबारा कनेक्ट होने से गलती से उपयोगकर्ता की कार्रवाई की घोषणा न हो जाए।
गुम या दोहराई गई सूचनाओं की जाँच करें
इवेंट फ़्लैग बदलने से पहले विफलता का कारण ढूँढ़ने के लिए दिखाई देने वाली दोनों स्थिति पंक्तियों का उपयोग करें। वे कंपोनेंट की सूचना में समस्या और पूर्वज तक डिलीवरी की समस्या के बीच अंतर बताती हैं।
- कोई भी स्थिति नहीं बदलती: डिस्पैच और रजिस्ट्रेशन पर इवेंट के नाम की तुलना करें, फिर जाँचें कि कस्टम एलिमेंट की परिभाषा और बटन हैंडलर चल रहे हैं। इस दस्तावेज़ में उपयोगकर्ता की सक्रियता से पहले उपभोक्ता लिसनर रजिस्टर किए जाते हैं।
- केवल सीधे लिसनर की स्थिति बदलती है:
bubblesजाँचें। बीच के किसी ऐसे हैंडलर को भी देखें जो प्रसार रोकता हो। - दूसरे कंपोनेंट के भीतर रखने पर ही डिलीवरी विफल होती है: उस मार्ग की shadow सीमा पहचानें और
composedजाँचें। - दोबारा कनेक्ट होने पर गिनती तेज़ी से बढ़ती है: बार-बार लिसनर रजिस्टर होने की जाँच करें, खासकर ऐसे नए अनाम फ़ंक्शनों की जो एलिमेंट के हर बार कनेक्ट होने पर बनाए जाते हैं।
बार-बार बनाए गए अनाम फ़ंक्शन अलग-अलग लिसनर ऑब्जेक्ट होते हैं, भले ही उनका स्रोत टेक्स्ट एक जैसा हो। स्थिर फ़ंक्शन रेफ़रेंस रखने से रजिस्ट्रेशन और सफ़ाई को समझना आसान होता है। addEventListener() लिसनर के capture विकल्प में भी अंतर करता है, जो प्रभावित करता है कि वह कब चलता है। addEventListener का दस्तावेज़।
कोई मूल click shadow tree के बाहर पहले से पहुँच सकता है, क्योंकि ब्राउज़र द्वारा डिस्पैच किए गए click composed होते हैं। जब उपभोक्ता को नामित कंपोनेंट कार्रवाई और निर्धारित पेलोड चाहिए, तब अलग कस्टम इवेंट उपयोगी होता है। दोनों सूचनाओं को एक ही एप्लिकेशन कार्रवाई की तरह हैंडल करने से बचें, जब तक ऐसा दोहराव जानबूझकर न किया गया हो। Event composed का दस्तावेज़।
अंत में, अपने इवेंट डिज़ाइन में सूचना और आगे बढ़ने की अनुमति को अलग रखें। यह उदाहरण डिस्पैच से पहले गिनती बढ़ाता है और इवेंट को noncancelable रखता है। preventDefault() कॉल करने वाला उपभोक्ता उस अपडेट को पलट नहीं सकता। Cancelable अनुरोध के लिए स्पष्ट कार्यान्वयन चाहिए, जो अनुरोधित कार्रवाई करने से पहले dispatchEvent() का रिटर्न मान जाँचे। dispatchEvent का रिटर्न मान।
इस काम के लिए पूरा अनुबंध छोटा है: एक आंतरिक बटन हैंडलर स्थिति अपडेट करता है, एक नामित कस्टम इवेंट होस्ट से निकलता है और उपभोक्ता उसका दस्तावेज़ीकृत पेलोड पढ़ते हैं। पहले सीधे लिसनर को काम करने दें, फिर वे प्रसार मार्ग सक्षम करें जिनकी आपके बाहरी इंटरफ़ेस को वास्तव में ज़रूरत है।
स्रोत
- HTML Standard — कस्टम एलिमेंट — WHATWG।
- DOM Standard — WHATWG।
- CustomEvent: CustomEvent() कंस्ट्रक्टर — MDN Web Docs।
- EventTarget: dispatchEvent() मेथड — MDN Web Docs।
- Event: composed प्रॉपर्टी — MDN Web Docs।
- कस्टम एलिमेंट का उपयोग — MDN Web Docs।
- EventTarget: addEventListener() मेथड — MDN Web Docs।
- EventTarget: removeEventListener() मेथड — MDN Web Docs।
- Mac पर TextEdit में HTML दस्तावेज़ों के साथ काम करें — Apple।