कस्टम एलिमेंट v1 - फिर से इस्तेमाल किए जा सकने वाले वेब कॉम्पोनेंट

कस्टम एलिमेंट की मदद से वेब डेवलपर, नए एचटीएमएल टैग तय कर सकते हैं, मौजूदा टैग बढ़ा सकते हैं, और फिर से इस्तेमाल किए जा सकने वाले वेब कॉम्पोनेंट बना सकते हैं.

कस्टम एलिमेंट की मदद से वेब डेवलपर, नए एचटीएमएल टैग बना सकते हैं, मौजूदा HTML टैग को बीफ़-अप करें या फिर अन्य डेवलपर के पास मौजूद कॉम्पोनेंट को बढ़ाएं लिखा गया है. API वेब का आधार है कॉम्पोनेंट के तौर पर दिखता है. इसकी मदद से, किसी भी वैनिला JS/HTML/CSS. इससे कोड और मॉड्यूलर कोड का कम इस्तेमाल होता है और कोड का ज़्यादा इस्तेमाल होता है हमारे ऐप्लिकेशन.

परिचय

वेब ऐप्लिकेशन की संरचना के लिए ब्राउज़र हमें एक बेहतरीन टूल देता है. यह समय है जिसे एचटीएमएल कहते हैं. आपने शायद इसके बारे में सुना हो! यह डिक्लेरेटिव, पोर्टेबल, और और साथ काम करने में आसान होते हैं. HTML शानदार हो सकता है, लेकिन इसकी शब्दावली और एक्सटेंशन सीमित हैं. एचटीएमएल लिविंग में, इस प्लैटफ़ॉर्म के स्टैंडर्ड अब तक के हिसाब से JS के व्यवहार को आपके मार्कअप से अपने-आप जोड़ेगा...

कस्टम एलीमेंट HTML को आधुनिक बनाने का जवाब हैं, जो अनुपलब्ध के टुकड़े, और बंडलिंग स्ट्रक्चर का इस्तेमाल किया जाता है. यदि HTML यह तो हम ऐसा कस्टम एलीमेंट बना सकते हैं जो कस्टम एलिमेंट, एचटीएमएल के फ़ायदों को सुरक्षित रखते हुए ब्राउज़र को नई तरकीबें सिखाते हैं.

नया एलिमेंट तय करना

नया एचटीएमएल एलिमेंट तय करने के लिए, हमें JavaScript की ताकत की ज़रूरत होती है!

customElements ग्लोबल का इस्तेमाल, पसंद के मुताबिक एलिमेंट तय करने और पढ़ाने के लिए किया जाता है ब्राउज़र पर जाएं. टैग नाम के साथ customElements.define() को कॉल करें एक ऐसा JavaScript class बनाना हो जो बेस HTMLElement को बढ़ाता हो.

उदाहरण - मोबाइल ड्रॉर पैनल को परिभाषित करना, <app-drawer>:

class AppDrawer extends HTMLElement {...}
window.customElements.define('app-drawer', AppDrawer);

// Or use an anonymous class if you don't want a named constructor in current scope.
window.customElements.define('app-drawer', class extends HTMLElement {...});

इस्तेमाल का उदाहरण:

<app-drawer></app-drawer>

यह याद रखना ज़रूरी है कि कस्टम एलिमेंट का इस्तेमाल करना, <div> या कोई दूसरा एलिमेंट इस्तेमाल करके. पेज पर इंस्टेंस दिए जा सकते हैं, JavaScript में डायनैमिक तौर पर बनाया जाता है, तो इवेंट लिसनर अटैच किए जा सकते हैं, वगैरह. Keep पढ़ें.

किसी एलिमेंट के लिए JavaScript API को तय करना

कस्टम एलिमेंट के फ़ंक्शन, ES2015 का इस्तेमाल करके तय किए गए हैं class जो HTMLElement तक सीमित है. HTMLElement को बढ़ाने से कस्टम एलिमेंट पक्का होता है इससे पूरा DOM API इनहेरिट किया जाता है. इसका मतलब है कि आप क्लास एलिमेंट के DOM इंटरफ़ेस का हिस्सा बन जाती है. ज़रूरी है कि क्लास का इस्तेमाल इन कामों के लिए करें अपने टैग के लिए सार्वजनिक JavaScript API बनाएं.

उदाहरण - <app-drawer> का DOM इंटरफ़ेस तय करना:

class AppDrawer extends HTMLElement {

  // A getter/setter for an open property.
  get open() {
    return this.hasAttribute('open');
  }

  set open(val) {
    // Reflect the value of the open property as an HTML attribute.
    if (val) {
      this.setAttribute('open', '');
    } else {
      this.removeAttribute('open');
    }
    this.toggleDrawer();
  }

  // A getter/setter for a disabled property.
  get disabled() {
    return this.hasAttribute('disabled');
  }

  set disabled(val) {
    // Reflect the value of the disabled property as an HTML attribute.
    if (val) {
      this.setAttribute('disabled', '');
    } else {
      this.removeAttribute('disabled');
    }
  }

  // Can define constructor arguments if you wish.
  constructor() {
    // If you define a constructor, always call super() first!
    // This is specific to CE and required by the spec.
    super();

    // Setup a click listener on <app-drawer> itself.
    this.addEventListener('click', e => {
      // Don't toggle the drawer if it's disabled.
      if (this.disabled) {
        return;
      }
      this.toggleDrawer();
    });
  }

  toggleDrawer() {
    // ...
  }
}

customElements.define('app-drawer', AppDrawer);

इस उदाहरण में, हम एक ऐसा पैनल बना रहे हैं जिसमें open प्रॉपर्टी, disabled है प्रॉपर्टी और एक toggleDrawer() तरीका होता है. यह प्रॉपर्टी को एचटीएमएल के तौर पर भी दिखाता है एट्रिब्यूट के बारे में ज़्यादा जानें.

कस्टम एलिमेंट की एक बेहतरीन सुविधा यह है कि क्लास की परिभाषा में this डीओएम एलिमेंट का इस्तेमाल करता है, जैसे कि क्लास का इंस्टेंस. हमारे उदाहरण के लिए, this का मतलब <app-drawer> है. इस (😉) में बताया है कि एलिमेंट कैसे काम कर सकता है click लिसनर को खुद ही अटैच करें! साथ ही, आप सिर्फ़ इवेंट सुनने वालों तक सीमित नहीं हैं. पूरा DOM API, एलिमेंट कोड में उपलब्ध होता है. इसे ऐक्सेस करने के लिए this का इस्तेमाल करें एलिमेंट की प्रॉपर्टी, इसके चाइल्ड (this.children), क्वेरी नोड की जांच करें (this.querySelectorAll('.items')), वगैरह

कस्टम एलिमेंट बनाने के नियम

  1. कस्टम एलिमेंट के नाम में डैश (-) होना चाहिए. इसलिए <x-tags>, <my-element> और <my-awesome-app> सभी मान्य नाम हैं, जबकि <tabs> और <foo_bar> नहीं हैं. यह ज़रूरी शर्त इसलिए तय की गई है, ताकि एचटीएमएल पार्सर कस्टम तत्वों और सामान्य तत्वों के बीच अंतर करना. इससे यह भी पक्का होता है कि साथ काम करता है.
  2. आप एक ही टैग को एक से ज़्यादा बार रजिस्टर नहीं कर सकते. ऐसा करने का प्रयास करने से DOMException फेंकें. ब्राउज़र को एक नए टैग के बारे में बताने के बाद, इसे. कोई बैक अप नहीं लिया जा सकता.
  3. कस्टम एलिमेंट अपने-आप बंद नहीं हो सकते, क्योंकि एचटीएमएल में कुछ ही एलिमेंट जो उस समय अपने-आप बंद हो जाए. हमेशा क्लोज़िंग टैग लिखें (<app-drawer></app-drawer>).

पसंद के मुताबिक एलिमेंट वाली प्रतिक्रियाएं

कोई कस्टम एलिमेंट, कोड चलाने के लिए खास लाइफ़साइकल हुक तय कर सकता है दिलचस्प दौर की शुरुआत हुई है. इन्हें कस्टम एलिमेंट कहा जाता है प्रतिक्रियाएं.

नाम कब कॉल किया
constructor एलिमेंट का एक इंस्टेंस यह है बनाया या अपग्रेड किया गया हो. शुरुआत करने में मदद मिलती है स्टेटस, इवेंट लिसनर सेट अप करना या शैडो डॉम बनाना. ज़्यादा जानकारी के लिए, खास जानकारी देखें कि constructor में क्या-क्या किया जा सकता है.
connectedCallback हर बार कॉल किया एलिमेंट को DOM में डाला जाता है. यह सेटअप कोड को चलाने में मदद करता है, जैसे कि संसाधन या रेंडरिंग को फ़ेच करने की सुविधा नहीं होती. आम तौर पर, आपको काम में देरी करनी चाहिए तक सीमित नहीं है.
disconnectedCallback एलिमेंट को डीओएम से हर बार हटाए जाने पर कॉल किया जाता है. इनके लिए उपयोगी है क्लीनअप कोड चलाने की सलाह देता है.
attributeChangedCallback(attrName, oldVal, newVal) यह तब कॉल किया जाता है, जब किसी निगरानी में रखा गया एट्रिब्यूट जोड़ा गया, हटाया गया, अपडेट किया गया या बदला गया. इसे शुरुआती वैल्यू के लिए भी कहा जाता है जब पार्सर ने कोई एलिमेंट बनाया हो या अपग्रेड किया गया. ध्यान दें: सिर्फ़ observedAttributes प्रॉपर्टी में मौजूद एट्रिब्यूट इस कॉलबैक को पाएं.
adoptedCallback कॉन्टेंट बनाने कस्टम एलिमेंट को नए document में ले जाया गया (उदाहरण के लिए, किसी व्यक्ति ने document.adoptNode(el) कॉल किया).

प्रतिक्रिया कॉलबैक सिंक्रोनस होते हैं. अगर कोई व्यक्ति el.setAttribute() को कॉल करता है एलिमेंट पर, ब्राउज़र तुरंत attributeChangedCallback() को कॉल करेगा. इसी तरह, आपको एलिमेंट के ठीक बाद disconnectedCallback() मिलेगा डीओएम से हटाया गया (उदाहरण के लिए, उपयोगकर्ता el.remove() को कॉल करता है).

उदाहरण: <app-drawer> में कस्टम एलिमेंट प्रतिक्रियाएं जोड़ना:

class AppDrawer extends HTMLElement {
  constructor() {
    super(); // always call super() first in the constructor.
    // ...
  }

  connectedCallback() {
    // ...
  }

  disconnectedCallback() {
    // ...
  }

  attributeChangedCallback(attrName, oldVal, newVal) {
    // ...
  }
}

अगर/जब ज़रूरी हो, तो प्रतिक्रियाओं को परिभाषित करें. अगर आपका एलिमेंट काफ़ी जटिल है और connectedCallback() में IndexedDB से कनेक्शन खोलता है, तो ज़रूरी disconnectedCallback() में क्लीनअप का काम. लेकिन सावधान रहें! आप अपनी एलिमेंट को सभी स्थितियों में DOM से हटाया जा रहा है. उदाहरण के लिए, अगर उपयोगकर्ता टैब बंद कर देता है, तो disconnectedCallback() को कभी कॉल नहीं किया जाएगा.

प्रॉपर्टी और एट्रिब्यूट

एट्रिब्यूट के हिसाब से प्रॉपर्टी देखना

एचटीएमएल प्रॉपर्टी के लिए यह आम बात है कि वे अपनी वैल्यू वापस डीओएम को एचटीएमएल एट्रिब्यूट. उदाहरण के लिए, जब hidden या id की वैल्यू बदली जाती हैं JS:

div.id = 'my-id';
div.hidden = true;

वैल्यू, लाइव डीओएम पर एट्रिब्यूट के तौर पर लागू होती हैं:

<div id="my-id" hidden>

इसे "प्रॉपर्टी को इस तरह से दिखाना है कि एट्रिब्यूट" का इस्तेमाल करें. एचटीएमएल की करीब-करीब हर प्रॉपर्टी ऐसा करती है. क्यों? एट्रिब्यूट इन कामों के लिए भी काम के होते हैं किसी एलिमेंट को एलान के तौर पर कॉन्फ़िगर करना. साथ ही, सुलभता और सीएसएस जैसे कुछ एपीआई सिलेक्टर अपने काम करने के लिए एट्रिब्यूट पर निर्भर करते हैं.

प्रॉपर्टी को हर उस जगह पर दिखाना उपयोगी होता है जहां आप एलिमेंट के DOM को बनाए रखना चाहते हैं को उसकी JavaScript स्थिति के साथ सिंक करके दिखाया जाना चाहिए. इसकी एक वजह प्रॉपर्टी को दिखाने से JS की स्थिति बदलने पर उपयोगकर्ता की तय की गई स्टाइल लागू होती है.

हमारे <app-drawer> को याद करें. इस कॉम्पोनेंट का इस्तेमाल करने वाला व्यक्ति, शायद इसे कम करना चाहता है और/या इसके बंद होने पर उपयोगकर्ता के इंटरैक्शन को रोकें:

app-drawer[disabled] {
  opacity: 0.5;
  pointer-events: none;
}

JS में disabled प्रॉपर्टी बदलने पर, हम चाहते हैं कि वह एट्रिब्यूट को DOM में जोड़ा जाता है, ताकि उपयोगकर्ता का सिलेक्टर मैच हो. एलिमेंट ऐसा कर सकता है व्यवहार:

get disabled() {
  return this.hasAttribute('disabled');
}

set disabled(val) {
  // Reflect the value of `disabled` as an attribute.
  if (val) {
    this.setAttribute('disabled', '');
  } else {
    this.removeAttribute('disabled');
  }
  this.toggleDrawer();
}

एट्रिब्यूट में किए गए बदलावों को देखना

एचटीएमएल एट्रिब्यूट, उपयोगकर्ताओं के लिए शुरुआती स्थिति बताने का आसान तरीका है:

<app-drawer open disabled></app-drawer>

एलिमेंट attributeChangedCallback. हर बदलाव के लिए, ब्राउज़र इस तरीके को कॉल करेगा observedAttributes कलेक्शन में मौजूद एट्रिब्यूट के लिए.

class AppDrawer extends HTMLElement {
  // ...

  static get observedAttributes() {
    return ['disabled', 'open'];
  }

  get disabled() {
    return this.hasAttribute('disabled');
  }

  set disabled(val) {
    if (val) {
      this.setAttribute('disabled', '');
    } else {
      this.removeAttribute('disabled');
    }
  }

  // Only called for the disabled and open attributes due to observedAttributes
  attributeChangedCallback(name, oldValue, newValue) {
    // When the drawer is disabled, update keyboard/screen reader behavior.
    if (this.disabled) {
      this.setAttribute('tabindex', '-1');
      this.setAttribute('aria-disabled', 'true');
    } else {
      this.setAttribute('tabindex', '0');
      this.setAttribute('aria-disabled', 'false');
    }
    // TODO: also react to the open attribute changing.
  }
}

उदाहरण में, हम <app-drawer> पर अतिरिक्त एट्रिब्यूट तब सेट करते हैं, जब disabled एट्रिब्यूट बदल गया है. हालांकि हम यहां ऐसा नहीं कर रहे हैं, लेकिन आप साथ ही किसी JS प्रॉपर्टी को इसके साथ सिंक रखने के लिए attributeChangedCallback का इस्तेमाल करें एट्रिब्यूट के बारे में ज़्यादा जानें.

एलिमेंट अपग्रेड

क्रमिक रूप से बेहतर एचटीएमएल

हम पहले ही जान चुके हैं कि कस्टम एलिमेंट को कॉल करने की सुविधा का इस्तेमाल करके तय किया जाता है customElements.define(). लेकिन इसका यह मतलब नहीं है कि आपको एक कस्टम एलिमेंट देखने की सुविधा मिलती है.

कस्टम एलिमेंट को डेफ़िनिशन के रजिस्टर होने से पहले इस्तेमाल किया जा सकता है.

प्रोग्रेसिव एन्हैंसमेंट, कस्टम एलिमेंट की एक सुविधा है. दूसरे शब्दों में, आपके पास पेज पर कई <app-drawer> एलिमेंट का एलान करें और कभी भी शुरू न करें customElements.define('app-drawer', ...). ऐसा इसलिए होता है, क्योंकि ब्राउज़र संभावित कस्टम तत्वों के साथ अलग तरीके से व्यवहार करता है, क्योंकि अज्ञात टैग. define() को कॉल करने और किसी मौजूदा सदस्यता को मैनेज करने की प्रोसेस क्लास डेफ़िनिशन वाले एलिमेंट को "एलिमेंट अपग्रेड" कहा जाता है.

टैग का नाम तय होने पर, window.customElements.whenDefined(). यह एक ऐसा प्रॉमिस देता है जो तब रिज़ॉल्व हो जाता है, जब एलिमेंट तय हो जाता है.

customElements.whenDefined('app-drawer').then(() => {
  console.log('app-drawer defined');
});

उदाहरण - चाइल्ड एलिमेंट के सेट को अपग्रेड किए जाने तक, काम में देरी करें

<share-buttons>
  <social-button type="twitter"><a href="...">Twitter</a></social-button>
  <social-button type="fb"><a href="...">Facebook</a></social-button>
  <social-button type="plus"><a href="...">G+</a></social-button>
</share-buttons>
// Fetch all the children of <share-buttons> that are not defined yet.
let undefinedButtons = buttons.querySelectorAll(':not(:defined)');

let promises = [...undefinedButtons].map((socialButton) => {
  return customElements.whenDefined(socialButton.localName);
});

// Wait for all the social-buttons to be upgraded.
Promise.all(promises).then(() => {
  // All social-button children are ready.
});

एलिमेंट के हिसाब से कॉन्टेंट

कस्टम एलिमेंट, अंदर मौजूद DOM API का इस्तेमाल करके अपने कॉन्टेंट को मैनेज कर सकते हैं एलिमेंट कोड. इसके लिए, प्रतिक्रियाएं काम की होती हैं.

उदाहरण - कुछ डिफ़ॉल्ट एचटीएमएल वाला एलिमेंट बनाएं:

customElements.define('x-foo-with-markup', class extends HTMLElement {
  connectedCallback() {
    this.innerHTML = "<b>I'm an x-foo-with-markup!</b>";
  }
  // ...
});

इस टैग को बताने से:

<x-foo-with-markup>
  <b>I'm an x-foo-with-markup!</b>
</x-foo-with-markup>

// TODO: DevSite - कोड का नमूना हटाया गया क्योंकि इसने इनलाइन इवेंट हैंडलर का इस्तेमाल किया

शैडो DOM का इस्तेमाल करने वाला एलिमेंट बनाना

शैडो डीओएम से एलिमेंट का मालिकाना हक, रेंडर, और स्टाइल बनाए रखने में मदद मिलती है ऐसा DOM जो पेज के बाकी हिस्से से अलग होता है. अरे, यहां तक कि आप सिर्फ़ एक टैग से सभी ऐप्लिकेशन के लिए:

<!-- chat-app's implementation details are hidden away in Shadow DOM. -->
<chat-app></chat-app>

किसी कस्टम एलिमेंट में शैडो डीओएम का इस्तेमाल करने के लिए, अपनेthis.attachShadow constructor:

let tmpl = document.createElement('template');
tmpl.innerHTML = `
  <style>:host { ... }</style> <!-- look ma, scoped styles -->
  <b>I'm in shadow dom!</b>
  <slot></slot>
`;

customElements.define('x-foo-shadowdom', class extends HTMLElement {
  constructor() {
    super(); // always call super() first in the constructor.

    // Attach a shadow root to the element.
    let shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.appendChild(tmpl.content.cloneNode(true));
  }
  // ...
});

इस्तेमाल का उदाहरण:

<x-foo-shadowdom>
  <p><b>User's</b> custom text</p>
</x-foo-shadowdom>

<!-- renders as -->
<x-foo-shadowdom>
  #shadow-root
  <b>I'm in shadow dom!</b>
  <slot></slot> <!-- slotted content appears here -->
</x-foo-shadowdom>

उपयोगकर्ता का कस्टम टेक्स्ट

// TODO: DevSite - कोड का नमूना हटाया गया क्योंकि इसने इनलाइन इवेंट हैंडलर का इस्तेमाल किया

<template> से एलिमेंट बनाना

जिन लोगों को इसके बारे में कोई जानकारी नहीं है उनके लिए, <template> एलिमेंट की मदद से, पार्स किए गए डीओएम के फ़्रैगमेंट के बारे में बताया जा सकता है, पेज लोड होने पर इनर्ट किया जा सकता है, और को बाद में रनटाइम पर चालू किया जा सकता है. यह वेब में इस्तेमाल किया जाने वाला एक और एपीआई है कॉम्पोनेंट फ़ैमिली. टेंप्लेट यह बताने के लिए एक आदर्श प्लेसहोल्डर होते हैं: कस्टम एलिमेंट का स्ट्रक्चर तय करें.

उदाहरण: किसी एलिमेंट को शैडो DOM कॉन्टेंट के साथ रजिस्टर करना <template>:

<template id="x-foo-from-template">
  <style>
    p { color: green; }
  </style>
  <p>I'm in Shadow DOM. My markup was stamped from a &lt;template&gt;.</p>
</template>

<script>
  let tmpl = document.querySelector('#x-foo-from-template');
  // If your code is inside of an HTML Import you'll need to change the above line to:
  // let tmpl = document.currentScript.ownerDocument.querySelector('#x-foo-from-template');

  customElements.define('x-foo-from-template', class extends HTMLElement {
    constructor() {
      super(); // always call super() first in the constructor.
      let shadowRoot = this.attachShadow({mode: 'open'});
      shadowRoot.appendChild(tmpl.content.cloneNode(true));
    }
    // ...
  });
</script>

कोड की ये कुछ लाइनें बहुत कारगर हैं. आइए, बाज़ार में होने वाली अहम चीज़ों के बारे में जानते हैं चालू है:

  1. हम एचटीएमएल में एक नया एलिमेंट तय कर रहे हैं: <x-foo-from-template>
  2. एलिमेंट के शैडो DOM को <template> से बनाया गया है
  3. शैडो डीओएम की वजह से, एलिमेंट का डीओएम, एलिमेंट के लिए लोकल है
  4. शैडो डीओएम की वजह से, एलिमेंट का इंटरनल सीएसएस, एलिमेंट तक सीमित है

मैं शैडो DOM में हूं. मेरे मार्कअप को <template> से स्टैंप किया गया था.

// TODO: DevSite - कोड का नमूना हटाया गया क्योंकि इसने इनलाइन इवेंट हैंडलर का इस्तेमाल किया

कस्टम एलिमेंट का लुक तय करना

भले ही आपका एलिमेंट, शैडो डीओएम का इस्तेमाल करके अपनी स्टाइल तय करता है, फिर भी उपयोगकर्ता अपने कस्टम एलिमेंट को उनके पेज से जोड़ सकते हैं. इन्हें "उपयोगकर्ता के लिए तय किए गए स्टाइल" कहा जाता है.

<!-- user-defined styling -->
<style>
  app-drawer {
    display: flex;
  }
  panel-item {
    transition: opacity 400ms ease-in-out;
    opacity: 0.3;
    flex: 1;
    text-align: center;
    border-radius: 50%;
  }
  panel-item:hover {
    opacity: 1.0;
    background: rgb(255, 0, 255);
    color: white;
  }
  app-panel > panel-item {
    padding: 5px;
    list-style: none;
    margin: 0 7px;
  }
</style>

<app-drawer>
  <panel-item>Do</panel-item>
  <panel-item>Re</panel-item>
  <panel-item>Mi</panel-item>
</app-drawer>

आपके मन में यह सवाल आ सकता है कि अगर एलिमेंट में स्टाइल हैं, तो सीएसएस की खासियत कैसे काम करती है शैडो DOM में परिभाषित किया गया है. खासियत के हिसाब से, उपयोगकर्ता की स्टाइल बेहतर होती है. वे हमेशा तत्व-तय स्टाइलिंग को ओवरराइड करता है. एलिमेंट बनाना जो शैडो DOM का इस्तेमाल करती है.

बिना रजिस्ट्रेशन वाले एलिमेंट को पहले से स्टाइल करना

किसी एलिमेंट को अपग्रेड करने से पहले, उसे सीएसएस में टारगेट करने के लिए, :defined pseudo-class. यह कॉम्पोनेंट को पहले से स्टाइल करने में मददगार होता है. इसके लिए उदाहरण के लिए, किसी तय वैल्यू को छिपाएं, ताकि लेआउट या दूसरे विज़ुअल FOUC को रोका जा सके करने के लिए इस्तेमाल किया जा सकता है.

उदाहरण - <app-drawer> को तय करने से पहले छिपाएं:

app-drawer:not(:defined) {
  /* Pre-style, give layout, replicate app-drawer's eventual styles, etc. */
  display: inline-block;
  height: 100vh;
  opacity: 0;
  transition: opacity 0.3s ease-in-out;
}

<app-drawer> तय होने के बाद, सिलेक्टर (app-drawer:not(:defined)) अब मेल नहीं खाता.

एलिमेंट बढ़ाना

Custom Elements API नए एचटीएमएल एलिमेंट बनाने में मदद करता है. हालांकि, यह अन्य कस्टम तत्वों या यहां तक कि ब्राउज़र के बिल्ट-इन एचटीएमएल को बढ़ाने के लिए भी उपयोगी होते हैं.

कस्टम एलिमेंट को बढ़ाना

किसी अन्य कस्टम एलीमेंट को उसकी क्लास डेफ़िनिशन को बढ़ाकर बढ़ाने का काम किया जाता है.

उदाहरण - <app-drawer> का दायरा बढ़ाने वाला <fancy-app-drawer> बनाएं:

class FancyDrawer extends AppDrawer {
  constructor() {
    super(); // always call super() first in the constructor. This also calls the extended class' constructor.
    // ...
  }

  toggleDrawer() {
    // Possibly different toggle implementation?
    // Use ES2015 if you need to call the parent method.
    // super.toggleDrawer()
  }

  anotherMethod() {
    // ...
  }
}

customElements.define('fancy-app-drawer', FancyDrawer);

नेटिव एचटीएमएल एलिमेंट को बढ़ाना

मान लें कि आपको एक आकर्षक <button> बनाना है. हमारी साइट पर <button> के काम करने के तरीके और उसके काम करने के तरीके के बारे में बताएं. एक बेहतर विकल्प यह है कि कस्टम एलिमेंट का इस्तेमाल करके, मौजूदा एलिमेंट को बेहतर बनाना.

पसंद के मुताबिक बनाया गया एलिमेंट ऐसा कस्टम एलिमेंट होता है जो में HTML टैग होते हैं. किसी मौजूदा अवधि को बढ़ाने का मुख्य फ़ायदा एलिमेंट में अपनी सभी सुविधाएं (DOM प्रॉपर्टी, मेथड, और सुलभता) हासिल करना शामिल है. प्रोग्रेसिव वेब लिखने का इससे बेहतर तरीका कोई नहीं है app की तुलना में मौजूदा एचटीएमएल को लगातार बेहतर बनाया जा रहा है एलिमेंट शामिल करें.

एलिमेंट को एक्सटेंड करने के लिए, आपको ऐसी क्लास डेफ़िनिशन बनानी होगी जो इनहेरिट करे सही DOM इंटरफ़ेस से. उदाहरण के लिए, ऐसा कस्टम एलिमेंट जो बड़ा हो जाता है <button> को HTMLElement के बजाय, HTMLButtonElement से इनहेरिट करना ज़रूरी है. इसी तरह, <img> को बढ़ाने वाले एलिमेंट के लिए भी HTMLImageElement का एक्सटेंशन होना ज़रूरी है.

उदाहरण - <button> को बड़ा किया जा रहा है:

// See https://html.spec.whatwg.org/multipage/indices.html#element-interfaces
// for the list of other DOM interfaces.
class FancyButton extends HTMLButtonElement {
  constructor() {
    super(); // always call super() first in the constructor.
    this.addEventListener('click', e => this.drawRipple(e.offsetX, e.offsetY));
  }

  // Material design ripple animation.
  drawRipple(x, y) {
    let div = document.createElement('div');
    div.classList.add('ripple');
    this.appendChild(div);
    div.style.top = `${y - div.clientHeight/2}px`;
    div.style.left = `${x - div.clientWidth/2}px`;
    div.style.backgroundColor = 'currentColor';
    div.classList.add('run');
    div.addEventListener('transitionend', (e) => div.remove());
  }
}

customElements.define('fancy-button', FancyButton, {extends: 'button'});

ध्यान दें कि नेटिव एक्सटेंशन का इस्तेमाल करने पर, define() को किए जाने वाले कॉल में थोड़ा बदलाव हो जाता है एलिमेंट. ज़रूरी तीसरे पैरामीटर से ब्राउज़र को पता चलता है कि आप किस टैग का इस्तेमाल कर रहे हैं बढ़ाया जा रहा है. यह ज़रूरी है, क्योंकि कई एचटीएमएल टैग एक ही डीओएम शेयर करते हैं इंटरफ़ेस पर कॉपी करने की सुविधा मिलती है. <section>, <address>, और <em> (अन्य के साथ) सभी शेयर करते हैं HTMLElement; <q> और <blockquote>, दोनों HTMLQuoteElement शेयर करते हैं; वगैरह... {extends: 'blockquote'} को तय करने से ब्राउज़र को यह पता चलता है कि आप <q> के बजाय <blockquote> सूप गया. HTML खास जानकारी देखें.

पसंद के मुताबिक बनाए गए बिल्ट-इन एलिमेंट के उपभोक्ता, इसका इस्तेमाल कई तरह से कर सकते हैं. वे ये काम कर सकते हैं नेटिव टैग में is="" एट्रिब्यूट जोड़कर, इसका एलान करें:

<!-- This <button> is a fancy button. -->
<button is="fancy-button" disabled>Fancy button!</button>

JavaScript में कोई इंस्टेंस बनाएं:

// Custom elements overload createElement() to support the is="" attribute.
let button = document.createElement('button', {is: 'fancy-button'});
button.textContent = 'Fancy button!';
button.disabled = true;
document.body.appendChild(button);

या new ऑपरेटर का इस्तेमाल करें:

let button = new FancyButton();
button.textContent = 'Fancy button!';
button.disabled = true;

यहां <img> का एक और उदाहरण दिया गया है.

उदाहरण - <img> को बड़ा किया जा रहा है:

customElements.define('bigger-img', class extends Image {
  // Give img default size if users don't specify.
  constructor(width=50, height=50) {
    super(width * 10, height * 10);
  }
}, {extends: 'img'});

उपयोगकर्ता इस कॉम्पोनेंट के बारे में यह बताते हैं:

<!-- This <img> is a bigger img. -->
<img is="bigger-img" width="15" height="20">

या JavaScript में कोई इंस्टेंस बनाएं:

const BiggerImage = customElements.get('bigger-img');
const image = new BiggerImage(15, 20); // pass constructor values like so.
console.assert(image.width === 150);
console.assert(image.height === 200);

अन्य जानकारी

अज्ञात एलिमेंट बनाम तय नहीं किए गए कस्टम एलिमेंट

HTML काम में लचीला और लचीला है. उदाहरण के लिए, किसी पेज पर <randomtagthatdoesntexist> और ब्राउज़र पूरी तरह से खुश है स्वीकार नहीं करेगा. गैर-मानक टैग क्यों काम करते हैं? इसका उत्तर है HTML खास जानकारी इसकी अनुमति देता है. जिन एलिमेंट को स्पेसिफ़िकेशन में तय नहीं किया जाता उन्हें इस फ़ॉर्मैट में पार्स किया जाता है HTMLUnknownElement.

यही बात कस्टम एलिमेंट पर भी लागू नहीं होती है. संभावित कस्टम तत्वों को पार्स किया गया है को HTMLElement के तौर पर, अगर उन्हें किसी मान्य नाम ("-" के साथ बनाया गया हो) के साथ बनाया गया हो. आपने लोगों तक पहुंचाया मुफ़्त में की जांच उस ब्राउज़र में कर सकते हैं, जो कस्टम एलिमेंट को सपोर्ट करता है. कंसोल को चालू करें: Ctrl+Shift+J (या Mac पर Cmd+Opt+J) डालें और कोड की ये लाइनें:

// "tabs" is not a valid custom element name
document.createElement('tabs') instanceof HTMLUnknownElement === true

// "x-tabs" is a valid custom element name
document.createElement('x-tabs') instanceof HTMLElement === true

एपीआई का संदर्भ

customElements ग्लोबल में, कस्टम डाइमेंशन के साथ काम करने के उपयोगी तरीके बताए गए हैं एलिमेंट.

define(tagName, constructor, options)

ब्राउज़र में एक नया कस्टम एलिमेंट तय करता है.

उदाहरण

customElements.define('my-app', class extends HTMLElement { ... });
customElements.define(
    'fancy-button', class extends HTMLButtonElement { ... }, {extends: 'button'});

get(tagName)

एक मान्य कस्टम एलीमेंट टैग नाम दिए जाने पर, एलीमेंट का कंस्ट्रक्टर लौटाता है. अगर एलिमेंट की कोई डेफ़िनिशन रजिस्टर नहीं की गई है, तो undefined दिखाता है.

उदाहरण

let Drawer = customElements.get('app-drawer');
let drawer = new Drawer();

whenDefined(tagName)

ऐसा प्रॉमिस रिटर्न करता है जो कस्टम एलिमेंट तय होने पर रिज़ॉल्व हो जाता है. अगर तत्व पहले से परिभाषित है, तो तुरंत समाधान करें. टैग का नाम न होने पर अस्वीकार कर दिया जाता है कस्टम एलिमेंट का मान्य नाम.

उदाहरण

customElements.whenDefined('app-drawer').then(() => {
  console.log('ready!');
});

इतिहास और ब्राउज़र सहायता

अगर पिछले कुछ सालों से वेब कॉम्पोनेंट को फ़ॉलो किया जा रहा है, तो जानें कि Chrome 36+ ने Custom Elements API का ऐसा वर्शन लागू किया जो customElements.define() के बजाय document.registerElement(). हो गया इसे स्टैंडर्ड का पुराना वर्शन माना जाता है, जिसे v0 कहा जाता है. customElements.define() नया लोकप्रिय है और ब्राउज़र वेंडर क्या हैं इसे लागू करना शुरू किया जा रहा है. इसे कस्टम एलिमेंट v1 कहते हैं.

अगर आपको पुराने v0 स्पेसिफ़िकेशन में दिलचस्पी है, तो html5rocks देखें लेख में बताया गया है.

ब्राउज़र समर्थन

Chrome 54 (स्थिति), Safari 10.1 (status) और Firefox 63 (स्थिति) में कस्टम एलिमेंट v1. एज शुरू हो गया है डेवलपमेंट.

कस्टम एलिमेंट का पता लगाने की सुविधा के लिए, window.customElements:

const supportsCustomElementsV1 = 'customElements' in window;

पॉलीफ़िल

जब तक ब्राउज़र समर्थन व्यापक रूप से उपलब्ध नहीं हो जाता, तब तक स्टैंडअलोन पॉलीफ़िल कस्टम एलिमेंट v1 के लिए उपलब्ध है. हालांकि, हम webcomponents.js का इस्तेमाल करने का सुझाव देते हैं लोडर का इस्तेमाल करें. लोडर यह सुविधा, सुविधा की पहचान करने की सुविधा का इस्तेमाल करके, सिर्फ़ ज़रूरी पोलीफ़िल को एसिंक्रोनस रूप से लोड करती है जो ब्राउज़र के लिए ज़रूरी है.

इसे इंस्टॉल करें:

npm install --save @webcomponents/webcomponentsjs

इस्तेमाल का तरीका:

<!-- Use the custom element on the page. -->
<my-element></my-element>

<!-- Load polyfills; note that "loader" will load these async -->
<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js" defer></script>

<!-- Load a custom element definitions in `waitFor` and return a promise -->
<script type="module">
  function loadScript(src) {
    return new Promise(function(resolve, reject) {
      const script = document.createElement('script');
      script.src = src;
      script.onload = resolve;
      script.onerror = reject;
      document.head.appendChild(script);
    });
  }

  WebComponents.waitFor(() => {
    // At this point we are guaranteed that all required polyfills have
    // loaded, and can use web components APIs.
    // Next, load element definitions that call `customElements.define`.
    // Note: returning a promise causes the custom elements
    // polyfill to wait until all definitions are loaded and then upgrade
    // the document in one batch, for better performance.
    return loadScript('my-element.js');
  });
</script>

नतीजा

कस्टम एलिमेंट, हमें ब्राउज़र में नए एचटीएमएल टैग तय करने के लिए एक नया टूल देते हैं और ऐसा करके, फिर से इस्तेमाल किए जा सकने वाले कॉम्पोनेंट बनाए जा सकते हैं. उन्हें दूसरे नए प्लैटफ़ॉर्म के साथ जोड़ें Shadow DOM और <template> जैसे प्रिमिटिव शामिल किए गए हैं और वेब कॉम्पोनेंट की तस्वीर:

  • फिर से इस्तेमाल किए जा सकने वाले कॉम्पोनेंट बनाने और उन्हें बढ़ाने के लिए, क्रॉस-ब्राउज़र (वेब स्टैंडर्ड).
  • शुरू करने के लिए, किसी लाइब्रेरी या फ़्रेमवर्क की ज़रूरत नहीं होती. वनिला JS/HTML FTW!
  • इससे मिलता-जुलता प्रोग्रामिंग मॉडल दिखता है. यह सिर्फ़ DOM/CSS/HTML है.
  • यह वेब प्लैटफ़ॉर्म की अन्य नई सुविधाओं (शैडो DOM, <template>, सीएसएस) के साथ अच्छे से काम करती है कस्टम प्रॉपर्टी वगैरह)
  • ब्राउज़र के DevTools के साथ बढ़िया तरीके से इंटिग्रेट किया गया है.
  • मौजूदा सुलभता सुविधाओं का फ़ायदा लें.