Özel Öğelerle İlgili En İyi Uygulamalar

Özel öğeler, kendi HTML etiketlerinizi oluşturmanıza olanak tanır. Bu kontrol listesi, yüksek kaliteli öğeler oluşturmanıza yardımcı olacak en iyi uygulamaları kapsar.

Özel öğeler, HTML'yi genişletmenize ve kendi etiketlerinizi tanımlamanıza olanak tanır. Bunlar inanılmaz derecede güçlü bir özelliktir, ancak aynı zamanda düşük seviyelidirler. Yani kendi öğenizi nasıl en iyi şekilde uygulayacağınız her zaman net değildir.

Mümkün olan en iyi deneyimleri oluşturmanıza yardımcı olmak için bu yapılacaklar listesini oluşturduk. İyi düşünülmüş bir özel öğe olmak için gerektiğini düşündüğümüz her şeyin dökümünü çıkar.

Yapılacaklar listesi

Gölge DOM

Stilleri kapsüllemek için bir gölge kökü oluşturun.

Why? Stilleri öğenizin gölge köküne kapsüllemek, nerede kullanıldığından bağımsız olarak çalışmasını sağlar. Bu, özellikle geliştirici, öğenizi başka bir öğenin gölge kökünün içine yerleştirmek istiyorsa önemlidir. Bu durum, onay kutusu veya radyo düğmesi gibi basit öğeler için bile geçerlidir. Gölge kökünüzün içindeki tek içerik, stillerin kendisi olabilir.
Örnek <howto-checkbox> öğesi.

Oluşturucuda gölge kökünüzü oluşturun.

Why? Oluşturucu, öğeniz hakkında özel bilgiye sahip olmanızdır. Diğer öğelerin takılmasını önlemek için uygulama ayrıntılarını ayarlamanın tam zamanı. Bu işlemi connectedCallback gibi daha sonraki bir geri çağırmada yapmak, öğenizin ayrılıp dokümana yeniden eklendiği durumlara karşı koruma sağlamanız gerektiği anlamına gelir.
Örnek <howto-checkbox> öğesi.

Öğenin oluşturduğu tüm alt öğeleri gölge köküne yerleştirin.

Why? Öğeniz tarafından oluşturulan alt öğeler, uygulamanızın bir parçasıdır ve gizli olmalıdır. Gölge kökü koruması olmadan, harici JavaScript istemeden bu alt öğelerin çalışmasını etkileyebilir.
Örnek <howto-tabs> öğesi.

Işık DOM alt öğelerini gölge DOM'unuza yansıtmak için <slot> alanını kullanın

Why? HTML alt öğeleri bileşeninizi daha hazır hale getirdiğinden, bileşeninizin kullanıcılarının bileşeninizdeki içeriği belirtmesine izin verin. Bir tarayıcı özel öğeleri desteklemediğinde, iç içe yerleştirilmiş içerik kullanılabilir, görünür ve erişilebilir durumda kalır.
Örnek <howto-tabs> öğesi.

inline varsayılan görünümünü tercih etmiyorsanız bir :host görüntüleme stili (ör. block, inline-block, flex) ayarlayın.

Why? Özel öğeler varsayılan olarak display: inline değerine sahiptir. Bu nedenle, width veya height öğelerinin ayarlanmasının herhangi bir etkisi olmaz. Bu durum genellikle geliştiriciler için bir sürpriz olarak karşımıza çıkar ve sayfanın tasarımıyla ilgili sorunlara yol açabilir. inline ekran kullanmayı tercih etmediğiniz sürece, her zaman varsayılan display değeri belirlemeniz gerekir.
Örnek <howto-checkbox> öğesi.

Gizli özelliğe uyan bir :host görüntüleme stili ekleyin.

Why? Varsayılan display stiline sahip özel bir öğe (ör. :host { display: block }), daha düşük belirginlik düzeyini yerleşik hidden özelliğini geçersiz kılar. Öğenizi display: none oluşturmak için hidden özelliğini ayarlamayı düşünüyorsanız bu durum sizi şaşırtabilir. Varsayılan display stiline ek olarak :host([hidden]) { display: none } ile hidden için destek ekleyin.
Örnek <howto-checkbox> öğesi.

Özellikler ve özellikler

Yazar tarafından belirlenen genel özellikleri geçersiz kılmayın.

Why? Genel özellikler, tüm HTML öğelerinde bulunan özelliklerdir. tabindex ve role buna örnek olarak verilebilir. Özel bir öğe, klavyeye odaklanılabilmesi için başlangıç tabindex değerini 0 olarak ayarlamak isteyebilir. Ancak, öğenizi kullanan geliştiricinin bunu başka bir değere ayarlayıp ayarlamadığını her zaman kontrol etmeniz gerekir. Örneğin, tabindex öğesini -1 olarak ayarlamışlarsa öğenin etkileşimli olmasını istemiyorlar demektir.
Örnek <howto-checkbox> öğesi. Bu durum, Sayfa yazarını geçersiz kılmayın.

Temel verileri (dizeler, sayılar, boole'ler) her zaman özellik veya özellik olarak kabul edin.

Why? Yerleşik eşdeğerleri gibi özel öğeler yapılandırılabilir olmalıdır. Yapılandırma, bildirimli şekilde, özellikler aracılığıyla veya zorunlu olarak JavaScript özellikleri aracılığıyla aktarılabilir. İdeal olarak her özelliğin, karşılık gelen bir mülke de bağlanması gerekir.
Örnek <howto-checkbox> öğesi.

Temel veri özelliklerini ve mülklerini, mülkten özelliğe doğru olacak şekilde (veya tam tersi) senkronize halde tutmayı hedefleyin.

Why? Kullanıcıların öğenizle nasıl etkileşimde bulunacağını hiçbir zaman bilemezsiniz. JavaScript'te bir özellik ayarlayıp getAttribute() gibi bir API kullanarak bu değeri okumayı bekleyebilirler. Her özelliğe karşılık gelen bir özellik varsa ve her ikisi de yansıtılıyorsa kullanıcıların öğenizle çalışması kolaylaşır. Başka bir deyişle, setAttribute('foo', value) çağrıldığında karşılık gelen bir foo özelliği de ayarlanmalıdır. Bunun tersi de geçerlidir. Elbette bu kuralın istisnaları vardır. Yüksek frekans özelliklerini (ör. currentTime) bir video oynatıcıda yansıtmamalısınız. Muhakeme yeteneğinizi kullanın. Kullanıcı bir mülk veya özellikle etkileşimde bulunuyormuş gibi görünüyorsa ve bunu yansıtmak zor değilse bunu yapın.
Örnek <howto-checkbox> öğesi. Bu konu, Yeniden girme sorunlarını önleme bölümünde ayrıntılı olarak açıklanmıştır.

Yalnızca zengin verileri (nesneler, diziler) özellik olarak kabul etmeyi hedefleyin.

Why? Genel olarak, özellikleri üzerinden zengin verileri (düz JavaScript nesneleri ve dizileri) kabul eden yerleşik HTML öğelerine örnek yoktur. Zengin veriler, yöntem çağrıları veya özellikler aracılığıyla kabul edilir. Zengin verileri özellik olarak kabul etmenin bazı dezavantajları vardır: Büyük bir nesneyi bir dizeye dönüştürmek pahalı olabilir ve tüm nesne referansları bu dizelendirme işleminde kaybolur. Örneğin, başka bir nesneye veya bir DOM düğümüne referans veren bir nesneyi dizelerseniz bu referanslar kaybolur.

Zengin veri özelliklerini özelliklere yansıtmayın.

Why? Zengin veri özelliklerinin özniteliklere yansıtılması gereksiz derecede pahalıdır ve aynı JavaScript nesnelerinin serileştirilmesini ve serileştirilmesini gerektirir. Yalnızca bu özellikle çözülebilecek bir kullanım alanınız yoksa büyük olasılıkla ondan kaçınmak en iyisidir.

Öğe yeni sürüme geçmeden önce ayarlanmış olabilecek özellikleri kontrol edin.

Why? Öğenizi kullanan bir geliştirici, tanımı yüklenmeden önce öğede özellik ayarlamayı deneyebilir. Bu durum özellikle geliştirici, yükleme bileşenlerini işleyen, bunları sayfaya damgalayan ve özelliklerini bir modele bağlayan bir çerçeve kullanıyorsa geçerlidir.
Örnek <howto-checkbox> öğesi. Özellikleri geçici hale getirme bölümünde daha ayrıntılı bilgi edinebilirsiniz.

Sınıfları kendi kendinize başvurmayın.

Why? Durumlarını belirtmesi gereken öğeler, bunu özellikleri kullanarak yapmalıdır. class özelliğinin genellikle öğenizi kullanan geliştiriciye ait olduğu kabul edilir. Bu özelliğe kendiniz yazmanız durumunda istemeden geliştirici sınıflarının üzerine gelebilirsiniz.

Etkinlikler

Dahili bileşen etkinliğine yanıt olarak etkinlikleri gönderin.

Why? Bileşeninizin özellikleri, örneğin bir zamanlayıcı veya animasyon tamamlanırsa ya da bir kaynağın yüklemesi tamamlandığında yalnızca bileşeninizin bildiği etkinliklere yanıt olarak değişen özelliklere sahip olabilir. Ana makineye bileşenin durumunun farklı olduğunu bildirmek için bu değişikliklere yanıt olarak etkinliklerin gönderilmesi faydalı olur.

Ana makine ayarına yanıt olarak (aşağı doğru veri akışı) etkinlik göndermeyin.

Why? Bir mülkün ana makine ayarına yanıt olarak etkinlik gönderilmesi gereksizdir (ana makine, yalnızca ayarladığı için geçerli durumu bilir). Bir mülkün ana makine ayarına yanıt olarak etkinliklerin gönderilmesi, veri bağlama sistemlerinde sonsuz döngülere neden olabilir.
Örnek <howto-checkbox> öğesi.

Açıklamalar

Sayfa yazarını geçersiz kılma

Öğenizi kullanan bir geliştirici, başlangıç durumlarının bazılarını geçersiz kılmak isteyebilir. Örneğin, ARIA role veya odaklanılabilirliğini tabindex ile değiştirme. Kendi değerlerinizi uygulamadan önce, bu ve diğer genel özelliklerin ayarlanıp ayarlanmadığını kontrol edin.

connectedCallback() {
  if (!this.hasAttribute('role'))
    this.setAttribute('role', 'checkbox');
  if (!this.hasAttribute('tabindex'))
    this.setAttribute('tabindex', 0);

Özellikleri yapay hale getirme

Geliştirici, tanımı yüklenmeden önce öğenizde bir özellik ayarlamayı deneyebilir. Bu durum özellikle geliştirici, yükleme bileşenlerini işleyen, bunları sayfaya yerleştiren ve özelliklerini bir modele bağlayan bir çerçeve kullanıyorsa geçerlidir.

Aşağıdaki örnekte Angular, modelinin isChecked özelliğini bildirimli şekilde onay kutusunun checked özelliğine bağlamaktadır. "Nasıl yapılır?" onay kutusunun tanımı geç yüklendiyse Angular, öğe yükseltilmeden önce işaretlenen özelliği ayarlamayı deneyebilir.

<howto-checkbox [checked]="defaults.isChecked"></howto-checkbox>

Özel bir öğe, örneğinde önceden ayarlanmış herhangi bir özellik olup olmadığını kontrol ederek bu senaryoyu ele almalıdır. <howto-checkbox>, bu kalıbı _upgradeProperty() adlı bir yöntem kullanarak gösterir.

connectedCallback() {
  ...
  this._upgradeProperty('checked');
}

_upgradeProperty(prop) {
  if (this.hasOwnProperty(prop)) {
    let value = this[prop];
    delete this[prop];
    this[prop] = value;
  }
}

_upgradeProperty(), yükseltilmemiş örnekteki değeri yakalar ve özel öğenin kendi özellik ayarlayıcısını gölgelendirmemesi için özelliği siler. Bu şekilde, öğenin tanımı nihayet yüklendiğinde, doğru durumu hemen yansıtabilir.

Yeniden girme sorunlarını önleme

Durumu temel bir mülke yansıtmak için attributeChangedCallback() kullanmak cazip bir fikir olabilir. Örneğin:

// When the [checked] attribute changes, set the checked property to match.
attributeChangedCallback(name, oldValue, newValue) {
  if (name === 'checked')
    this.checked = newValue;
}

Ancak özellik ayarlayıcının özelliği de yansıtması durumunda bu, bir sonsuz döngü oluşturabilir.

set checked(value) {
  const isChecked = Boolean(value);
  if (isChecked)
    // OOPS! This will cause an infinite loop because it triggers the
    // attributeChangedCallback() which then sets this property again.
    this.setAttribute('checked', '');
  else
    this.removeAttribute('checked');
}

Alternatif bir yöntem de, özellik ayarlayıcının özelliğe yansıtmasına izin vermek ve getter'in, özelliğin değerini özelliğe dayalı olarak belirlemesini sağlamaktır.

set checked(value) {
  const isChecked = Boolean(value);
  if (isChecked)
    this.setAttribute('checked', '');
  else
    this.removeAttribute('checked');
}

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

Bu örnekte, özelliğin eklenmesi veya kaldırılması da mülkü ayarlar.

Son olarak attributeChangedCallback(), ARIA durumlarını uygulama gibi yan etkilerle başa çıkmak için kullanılabilir.

attributeChangedCallback(name, oldValue, newValue) {
  const hasValue = newValue !== null;
  switch (name) {
    case 'checked':
      // Note the attributeChangedCallback is only handling the *side effects*
      // of setting the attribute.
      this.setAttribute('aria-checked', hasValue);
      break;
    ...
  }
}