Custom Elements v1 - Yeniden Kullanılabilir Web Bileşenleri

Özel öğeler, web geliştiricilerinin yeni HTML etiketleri tanımlamalarına, mevcut etiketleri genişletmelerine ve yeniden kullanılabilir web bileşenleri oluşturmalarına olanak tanır.

Özel Öğeler ile web geliştiricileri yeni HTML etiketleri oluşturabilir, mevcut HTML etiketlerini güçlendirmek veya diğer geliştiricilerin sahip olduğu bileşenleri genişletmek yazar. API, Google Cloud'un tümünde bileşenleri hakkında daha fazla bilgi edinin. Web'in yeniden kullanılabilir bileşenler oluşturmanın standartlara dayalı bir yolunu ele alacağız. Bu da daha az kod, modüler kod ve her yerde daha fazla üretmek için çalışan ekiplere destek sağlıyorum.

Giriş

Tarayıcı, web uygulamalarını yapılandırmak için bize mükemmel bir araç sunuyor. İnsanların kullanıyor. Bunu duymuş olabilirsiniz. Hem bildirimsel hem de taşınabilir ve kolayca çalışabilmeniz sağlanır. HTML ne kadar iyi olursa, kelime dağarcığı ve genişletilebilirlik sınırlıdır. Canlı HTML standart yaklaşımında daima şimdiye kadar JS davranışını işaretlemenizle otomatik olarak ilişkilendirir.

Özel öğeler, HTML'yi modernleştirmenin ve eksik öğeleri düzeltmenin cevabıdır ve yapıyı davranışla gruplandırmaktır. HTML, yapan özel bir öğe oluşturabiliriz. Özel öğeleri, HTML'nin avantajlarını korurken tarayıcıya yeni numaralar öğretir.

Yeni bir öğe tanımlama

Yeni bir HTML öğesi tanımlamak için JavaScript'in gücüne ihtiyacımız vardır!

customElements global, özel bir öğeyi tanımlamak ve öğretmek için kullanılır kontrol edin. Etiket adıyla customElements.define() çağrısı yapın ve temel HTMLElement tabanını genişleten bir JavaScript class oluşturmak istiyorsunuz.

Örnek - <app-drawer> mobil çekmece paneli tanımlama:

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 {...});

Örnek kullanım:

<app-drawer></app-drawer>

Özel öğe kullanmanın <div> veya başka bir öğe kullanarak. Örnekler sayfada tanımlanabilir. JavaScript'te dinamik olarak oluşturulur, etkinlik işleyiciler eklenebilir vb. daha fazla örnek için okumaya devam edin.

Bir öğenin JavaScript API'sini tanımlama

Özel öğelerin işlevleri ES2015 kullanılarak tanımlanır class ve HTMLElement uzantısına sahip. HTMLElement işlevinin genişletilmesi, özel öğenin DOM API'nin tamamını devralır ve sınıfı, öğenin DOM arayüzünün bir parçası haline gelir. Özetle, sınıfını şu amaçlarla kullanabilirsiniz: Etiketiniz için herkese açık JavaScript API'si oluşturun.

Örnek - <app-drawer> öğesinin DOM arayüzünü tanımlama:

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);

Bu örnekte, open özelliği (disabled) olan bir çekmece oluşturuyoruz. özelliği ve bir toggleDrawer() yöntemi. Ayrıca, özellikleri HTML özellikleri ile birlikte kullanılamaz.

Özel öğelerin bir diğer güzel özelliği, sınıf tanımı içindeki this öğesinin DOM öğesinin kendisi (sınıfın örneği) anlamına gelir. Şurada: Örneğin this, <app-drawer> anlamına gelir. Öğe, bu şekilde (😉) kendisine bir click işleyicisi ekleyin! Bunlar etkinlik dinleyicileriyle sınırlı değildir. DOM API'sinin tamamı öğe kodunun içinde kullanılabilir. Şuna erişmek için this kullanın: öğenin özelliklerini, alt öğelerini (this.children), sorgu düğümlerini inceleyin (this.querySelectorAll('.items')) vb.

Özel öğe oluşturma kuralları

  1. Özel öğenin adı tire (-) içermelidir. <x-tags>, <my-element> ve <my-awesome-app> geçerli adlardır; <tabs> ise ve <foo_bar> değil. Bu gereksinim, HTML ayrıştırıcının özel öğeleri normal öğelerden ayırt edebilirsiniz. Ayrıca ekip üyelerinin yeni etiketler HTML'ye eklendiğinde uyumluluk sağlar.
  2. Aynı etiketi birden çok kez kaydedemezsiniz. Bunu yapmaya çalışırsanız DOMException atın. Tarayıcıya yeni bir etiketi bildirdikten sonra, somut olarak ortaya koyar. Geri almak yok.
  3. HTML yalnızca birkaç belleğe izin verdiğinden, özel öğeler kendi kendine kapanamaz öğeler kabul etmesini sağlar. Her zaman kapanış etiketi yaz (<app-drawer></app-drawer>).

Özel öğe tepkileri

Özel bir öğe, işlem sırasında kod çalıştırmak için özel yaşam döngüsü kancaları tanımlayabilir ortaya çıktığını gösteriyor. Bunlara özel öğe tepkiler bölümüne bakın.

Ad Şu durumda aranır:
constructor Öğenin bir örneği oluşturulmalı veya yeni sürüme geçirilmiş olmalıdır. Başlatma için kullanışlıdır etkinlik işleyicileri ayarlayarak veya gölge alanı oluşturarak. Bkz. spesifikasyon 'nı inceleyin. constructor sayfasında yapabileceklerinizle ilgili kısıtlamaları gözden geçirin.
connectedCallback Her seferinde öğesi DOM'ye eklenir. Örneğin, oluşturma veya oluşturmayı öğrendiniz. Genel olarak çalışmayı ertelemeye devam edecek.
disconnectedCallback Öğe DOM'den her kaldırıldığında çağrılır. Şunlar için yararlıdır: çalıştırma kodundan bahsedeceğim.
attributeChangedCallback(attrName, oldVal, newVal) Gözlemlenen bir özellik yapıldığında çağrılır eklenen, kaldırılan, güncellenen veya değiştirilen Başlangıç değerleri için de çağrılır Ayrıştırıcı tarafından bir öğe oluşturulduğunda veya yeni sürüme geçirildi. Not: yalnızca observedAttributes özelliğinde listelenen özellikler bu geri aramayı alabilirsiniz.
adoptedCallback İlgili içeriği oluşturmak için kullanılan özel öğe, yeni bir document içine taşındı (ör. document.adoptNode(el) adlı kişi) oturum açın.

Tepki geri çağırmaları eşzamanlıdır. Bir kullanıcı el.setAttribute() adlı kişiyi ararsa kullanırsanız tarayıcı hemen attributeChangedCallback() öğesini çağırır. Benzer şekilde, öğeniz şu şekilde ayarlandıktan hemen sonra bir disconnectedCallback() alırsınız: DOM'den kaldırılmış (ör. kullanıcı el.remove() çağrısı yapıyor).

Örnek: <app-drawer> için özel öğe tepkileri ekleme:

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

  connectedCallback() {
    // ...
  }

  disconnectedCallback() {
    // ...
  }

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

Uygun olduğunda/gerektiğinde tepkileri tanımlayın. Öğeniz yeterince karmaşıksa ve connectedCallback() içinde IndexedDB için bir bağlantı açarsa disconnectedCallback() bölgesinde temizlik çalışması yapıldı. Ancak dikkatli olun! Yapacağınız her şeyden önce öğesinin DOM'den kaldırılmasını sağlayabilirsiniz. Örneğin, Kullanıcı sekmeyi kapatırsa disconnectedCallback() hiçbir zaman çağrılmaz.

Özellikler

Özellikleri özelliklere yansıtma

HTML özelliklerinin, değerlerini DOM'ye bir HTML özelliği. Örneğin, hidden veya id değerleri JS:

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

değerler, yayındaki DOM'ye özellikler olarak uygulanır:

<div id="my-id" hidden>

Buna "özellikleri özellikleri" gibi bir değer kullanabilirsiniz. HTML'deki neredeyse her mülk bu işlemi gerçekleştirir. Neden? Özellikler aşağıdakiler için de yararlıdır: bir öğeyi bildirimli şekilde yapılandırma ile erişilebilirlik ve CSS gibi belirli API'ler seçicilerin çalışması için özellikler gerekir.

Bir özelliğin yansıması, öğenin DOM'sini tutmak istediğiniz her yerde yararlıdır. temsilini JavaScript durumuyla senkronize edin. Paydaşlarla iletişime geçmek bir özelliği yansıtır. Böylece, JS durumu değiştiğinde kullanıcı tanımlı stil uygulanır.

<app-drawer> numaralı telefonumuzu hatırlayın. Bu bileşenin tüketicisi, parçayı karartmak isteyebilir ve/veya devre dışı bırakıldığında kullanıcı etkileşimini engelleyebilir:

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

JS'de disabled özelliği değiştirildiğinde, bu özelliğin şu şekilde olmasını istiyoruz: kullanıcının seçicisinin eşleşmesi için DOM'ye eklenir. İlgili öğe, davranışına örnek gösterebiliriz:

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();
}

Özelliklerdeki değişiklikleri gözlemleme

HTML özellikleri, kullanıcıların başlangıç durumunu bildirmeleri için pratik bir yoldur:

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

Öğeler, tanımlarını kullanarak özellik değişikliklerine tepki verebilir. attributeChangedCallback Tarayıcı her değişiklik için bu yöntemi çağırır observedAttributes dizisinde listelenen özelliklere ekler.

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.
  }
}

Bu örnekte, bir kullanıcı aşağıdaki işlemleri gerçekleştirdiğinde <app-drawer> için ek özellikler ayarlıyoruz: disabled özelliği değiştirildi. Bunu burada yapmasak da, bir JS özelliğiniattributeChangedCallback özelliği ekleyin.

Öğeleri yeni sürüme geçirme

Kademeli olarak geliştirilmiş HTML

Özel öğelerin customElements.define() Ancak bu, bir web sitesini ziyaret etmek için bir arada kullanabilirsiniz.

Özel öğeler, tanımları kaydedilmeden önce kullanılabilir.

Progresif geliştirme, özel öğelerden oluşan bir özelliktir. Başka bir deyişle, sayfada bir grup <app-drawer> öğesi beyan eder ve hiçbir zaman çağırmaz customElements.define('app-drawer', ...) tarihine kadar devam edebilirsiniz. Bunun nedeni, Tarayıcı, bilinmeyen özel öğeleri nedeniyle etiketleri kullanın. define() çağrısı yapma ve mevcut bir öğesine "öğe yükseltmeleri" adı verilir.

Bir etiket adının ne zaman tanımlandığını öğrenmek için window.customElements.whenDefined() öğesi tanımlanır.

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

Örnek - bir alt öğe grubu yeni sürüme geçirilene kadar işi erteleme

<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.
});

Öğe tanımlı içerik

Özel öğeler, içindeki DOM API'lerini kullanarak kendi içeriklerini yönetebilir. öğe kodudur. Tepkiler bunun için yararlıdır.

Örnek: Varsayılan HTML içeren bir öğe oluşturun:

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

Bu etiket tanımlandığında şu sonuçlar elde edilir:

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

// YAPILACAKLAR: DevSite - Satır içi etkinlik işleyicileri kullandığı için kod örneği kaldırıldı

Gölge DOM kullanan bir öğe oluşturma

Gölge DOM, bir öğenin bir yığına sahip olması, oluşturması ve stilini belirlemesi için bir yol sağlar DOM'ye eklemeniz gerekir. Hatta bazen her hafta uygulamanın tamamını tek bir etiket içinde saklar:

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

Özel bir öğede Gölge DOM kullanmak içinthis.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));
  }
  // ...
});
.

Örnek kullanım:

<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>

Kullanıcının özel metni

// YAPILACAKLAR: DevSite - Satır içi etkinlik işleyicileri kullandığı için kod örneği kaldırıldı

<template> öğesinden öğe oluşturma

Bilmeyenler için, <template> öğe ayrıştırılan, sayfa yüklemede sabit olmayan ve daha sonra çalışma zamanında etkinleştirilebilir. Web'deki başka bir temel API öğesidir bileşen ailesi. Şablonlar, kampanya türünü tanımlamak için ideal bir yer tutucudur yapısı hakkında daha fazla bilgi.

Örnek: <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>

Bu birkaç kod satırı gerçekten çok etkili. Şimdiyse proje yönetiminde tarih:

  1. HTML'de yeni bir öğe tanımlıyoruz: <x-foo-from-template>
  2. Öğenin Gölge DOM'u bir <template> öğesinden oluşturulur
  3. Öğenin DOM'u, Gölge DOM'u sayesinde öğenin DOM'udur
  4. Öğenin dahili CSS'si, Gölge DOM sayesinde öğeyi kapsar.

Shadow DOM'deyim. İşaretlemem bir <template> şablonundan damgalandı.

// YAPILACAKLAR: DevSite - Satır içi etkinlik işleyicileri kullandığı için kod örneği kaldırıldı

Özel öğelerin stilini belirleme

Öğeniz Gölge DOM kullanarak kendi stilini tanımlasa bile kullanıcılar otomatik olarak eklenir. Bunlara "kullanıcı tanımlı stiller" denir.

<!-- 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>

Öğenin stilleri varsa CSS spesifikliğinin nasıl çalıştığını kendinize soruyor olabilirsiniz. Gölge DOM'de tanımlanmıştır. Kesinlik açısından kullanıcı stilleri kazanır. Onlar, öğe tanımlı stili her zaman geçersiz kılar. Öğe oluşturma bir kontrol listesidir.

Kayıtlı olmayan öğelerin önceden stilini belirleme

Bir öğe yeni sürüme geçirilmeden önce şu öğeyi kullanarak CSS'de öğeyi hedefleyebilirsiniz: :defined gerçek olmayan sınıf. Bu, bir bileşenin önceden stilini belirlerken yararlı olur. Örneğin, tanımlanamayan yerleşimleri gizleyerek düzeni veya diğer görsel ve tanımlandıklarında bunların kademeli olarak soluklaşmasını sağlayabilirsiniz.

Örnek - <app-drawer> tanımlanmadan önce gizlenir:

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> tanımlandıktan sonra, seçici (app-drawer:not(:defined)) artık eşleşmiyor.

Öğeleri genişletme

Custom Elements API'si yeni HTML öğeleri oluşturmak için yararlı olmakla birlikte aynı zamanda diğer özel öğelerin veya tarayıcının yerleşik HTML'sinin bile genişletilmesi için kullanışlıdır.

Özel öğeyi genişletme

Başka bir özel öğenin sınıf tanımı genişletilerek genişletme işlemi yapılır.

Örnek - <app-drawer> kapsamını genişleten <fancy-app-drawer> oluşturun:

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);

Yerel HTML öğelerini genişletme

Daha özel bir <button> oluşturmak istediğinizi varsayalım. Aynı bilgileri tekrar tekrar <button> ürününün işlevselliğini ve davranışını kademeli olarak artırmak daha iyi bir seçenektir. özel öğeler kullanarak mevcut öğeyi geliştirin.

Özelleştirilmiş yerleşik öğe, tarayıcının yerleşik HTML etiketlerini kullanır. Mevcut bir süreyi uzatmanın birincil faydası öğesi, tüm özelliklerinden (DOM özellikleri, yöntemler, erişilebilirlik) elde etmektir. Progresif web (progresif web) yazmanın daha iyi bir yolu uygulaması ile mevcut HTML'yi kademeli olarak iyileştirin öğeleri arasında yer alır.

Bir öğeyi genişletmek için doğru DOM arayüzünden kaldırın. Örneğin, <button> öğesinin, HTMLElement yerine HTMLButtonElement ayarından devralması gerekiyor. Benzer şekilde, <img> öğesini genişleten bir öğenin HTMLImageElement öğesini genişletmesi gerekir.

Örnek - <button> uzantısı uzatılıyor:

// 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'});

Yerel bir dosyayı genişletirken define() çağrısının biraz değiştiğine dikkat edin öğesine dokunun. Gerekli üçüncü parametre, tarayıcıya hangi etiketi uzatılıyor. Birçok HTML etiketi aynı DOM'yi paylaştığından bu gereklidir kullanır. <section>, <address> ve <em> (diğerlerinin yanı sıra) hepsini paylaşıyor HTMLElement; hem <q> hem de <blockquote>, HTMLQuoteElement değerini paylaşıyor; vb. {extends: 'blockquote'} belirtmek, tarayıcının bir <q> yerine <blockquote> çorbası. HTML'ye bakın. özellikler sayfasını ziyaret edin.

Özelleştirilmiş bir yerleşik öğenin tüketicileri bunu birkaç şekilde kullanabilir. Şunları yapabilirler: bunu yerel etikete is="" özelliğini ekleyerek bildirin:

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

JavaScript'te bir örnek oluşturun:

// 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);

veya new operatörünü kullanın:

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

İşte <img> kapsamını genişleten başka bir örnek.

Örnek - <img> uzantısı uzatılıyor:

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'});

Kullanıcılar bu bileşeni şu şekilde beyan eder:

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

veya JavaScript'te bir örnek oluşturun:

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);

Çeşitli ayrıntılar

Bilinmeyen öğeler ile tanımlanmamış özel öğeler karşılaştırması

HTML esnek ve esnek bir çalışma şeklidir. Örneğin, şunu tanımlayın: Bir sayfada <randomtagthatdoesntexist> ve tarayıcı son derece mutlu kabullenmek de önemlidir. Standart olmayan etiketler neden çalışır? Yanıt, HTML spesifikasyon izin verir. Spesifikasyon tarafından tanımlanmayan öğeler şu şekilde ayrıştırılır: HTMLUnknownElement

Bu durum, özel öğeler için geçerli değildir. Olası özel öğeler ayrıştırılır geçerli bir adla ("-" içeren) oluşturuldularsa HTMLElement olarak görünürler. Siz bunu, özel öğeleri destekleyen bir tarayıcıda kontrol edebilirsiniz. Konsolu çalıştırın: Ctrl+Üst Karakter+J (veya Mac'te Cmd+Opt+J) tuşlarına basın ve şu kod satırlarını kullanın:

// "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

API referansı

customElements global, özel boyutlarla çalışmak için yararlı yöntemler tanımlar öğeler.

define(tagName, constructor, options)

Tarayıcıda yeni bir özel öğe tanımlar.

Örnek

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

get(tagName)

Geçerli bir özel öğe etiketi adı verildiğinde, öğenin kurucusunu döndürür. Kayıtlı öğe tanımı yoksa undefined değerini döndürür.

Örnek

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

whenDefined(tagName)

Özel öğe tanımlandığında çözümlenen bir Vaat döndürür. Öğe öğesi zaten tanımlıysa hemen çözün. Etiket adı uygun değilse reddedilir geçerli bir özel öğe adı olmalıdır.

Örnek

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

Geçmiş ve tarayıcı desteği

Son birkaç yıldır web bileşenlerini takip ediyorsanız Chrome 36 ve sonraki sürümlerde Custom Elements API'nin customElements.define() yerine document.registerElement(). Bu kadar standardın v0 adı verilen kullanımdan kaldırılmış bir sürümü olarak kabul edilir. customElements.define() yeni popülerlik ve tarayıcı tedarikçi firmaları zaman çizelgesi oluşturur. Adı Custom Elements v1.

Eski v0 spesifikasyonuyla ilgileniyorsanız html5rocks makalesine bakın.

Tarayıcı desteği

Chrome 54 (durum), Safari 10.1 (durum) ve Firefox 63 (durum) Özel Öğeler v1. Edge, hakkında daha fazla bilgi edinin.

Özel öğeleri algılamak için mevcut olup olmadığını kontrol edin window.customElements:

const supportsCustomElementsV1 = 'customElements' in window;

Çoklu Dolgu

Tarayıcı desteği yaygın olarak sunulana kadar bağımsız çoklu dolgu özel öğeler v1'de kullanılabilir. Ancak, şunu kullanmanızı öneririz: webcomponents.js yükleyici en iyi şekilde yüklemenizi sağlar. Yükleyici yalnızca gerekli anket dolgularını eşzamansız olarak yüklemek için özellik algılamayı kullanır tarayıcı tarafından gerekli kılınır.

Yükleyin:

npm install --save @webcomponents/webcomponentsjs

Kullanım:

<!-- 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>
.

Sonuç

Özel öğeler, tarayıcıda yeni HTML etiketleri tanımlamak için bize yeni bir araç sunar ve ve yeniden kullanılabilir bileşenler oluşturmak. Bunları diğer yeni platformla birleştirin ve <template> gibi temel unsurların yanı sıra büyük farkların Web Bileşenlerinin resmi:

  • Yeniden kullanılabilir bileşenler oluşturmak ve genişletmek için tarayıcılar arası (web standardı).
  • Başlamak için kitaplık veya çerçeve gerekmez. Vanilla JS/HTML FTW!
  • Tanıdık bir programlama modeli sunar. Bu, yalnızca DOM/CSS/HTML'dir.
  • Diğer yeni web platformu özellikleriyle (Shadow DOM, <template>, CSS) uyumlu bir şekilde çalışır özel özellikler vb.)
  • Tarayıcının Geliştirici Araçları ile güçlü bir şekilde entegre edilmiştir.
  • Mevcut erişilebilirlik özelliklerinden yararlanın.