1. Giriş
Son Güncelleme: 2021-08-10
Web Bileşenleri
Web bileşenleri, web sayfalarında ve web uygulamalarında kullanmak üzere yeni özel, yeniden kullanılabilir, kapsüllenmiş HTML etiketleri oluşturmanıza olanak tanıyan bir grup web platformu API'sidir. Web bileşeni standartlarına göre oluşturulan özel bileşenler ve widget'lar modern tarayıcılarda çalışır ve HTML ile çalışan herhangi bir JavaScript kitaplığı veya çerçevesiyle kullanılabilir.
Lit nedir?
Lit, herhangi bir çerçevede veya çerçeve olmadan çalışan hızlı ve hafif web bileşenleri oluşturmak için kullanılan basit bir kitaplıktır. Lit ile paylaşılabilir bileşenler, uygulamalar, tasarım sistemleri ve daha fazlasını oluşturabilirsiniz.
Lit, özellikleri ve özellikleri yönetme, oluşturma gibi yaygın Web Bileşenleri görevlerini basitleştirmek için API'ler sağlar.
Neler öğreneceksiniz?
- Web bileşeni nedir?
- Web bileşenleri kavramları
- Web bileşeni oluşturma
- lit-html ve LitElement nedir?
- Lit'in web bileşeninin üzerinde yaptığı işlemler
Ne oluşturacaksınız?
- Vanilla beğenme / beğenmeme Web Bileşeni
- Beğenme / beğenmeme Lit tabanlı web bileşeni
Gerekenler
- Güncellenmiş herhangi bir modern tarayıcı (Chrome, Safari, Firefox, Chromium Edge). Web bileşenleri tüm modern tarayıcılarda çalışır. Microsoft Internet Explorer 11 ve Chromium olmayan Microsoft Edge için polyfill'ler mevcuttur.
- HTML, CSS, JavaScript ve Chrome Geliştirici Araçları hakkında bilgi sahibi olmak
2. Playground'u kurma ve keşfetme
Koda erişme
Bu kod laboratuvarı boyunca Lit Playground'a yönlendiren bağlantılar göreceksiniz. Örneğin:
Playground, tamamen tarayıcınızda çalışan bir kod korumalı alanıdır. TypeScript ve JavaScript dosyalarını derleyip çalıştırabilir ve içe aktarmaları otomatik olarak düğüm modüllerine çözümleyebilir. Örneğin:
// before
import './my-file.js';
import 'lit';
// after
import './my-file.js';
import 'https://unpkg.com/lit?module';
Bu kontrol noktalarını başlangıç noktası olarak kullanarak eğitimin tamamını Lit Playground'da yapabilirsiniz. VS Code kullanıyorsanız bu kontrol noktalarını kullanarak herhangi bir adımın başlangıç kodunu indirebilir ve çalışmanızı kontrol edebilirsiniz.
Exploring the lit playground UI

Lit playground kullanıcı arayüzü ekran görüntüsünde, bu codelab'de kullanacağınız bölümler vurgulanmıştır.
- Dosya seçici. Artı düğmesini bulun...
- Dosya düzenleyici.
- Kod önizlemesi.
- Yeniden yükle düğmesi.
- İndir düğmesi.
VS Code kurulumu (Gelişmiş)
Bu VS Code kurulumunu kullanmanın avantajları şunlardır:
- Şablon türü kontrolü
- Şablon intellisense ve otomatik tamamlama
NPM, VS Code (lit-plugin eklentisiyle birlikte) zaten yüklüyse ve bu ortamı nasıl kullanacağınızı biliyorsanız aşağıdaki adımları uygulayarak bu projeleri indirip başlatabilirsiniz:
- İndir düğmesine basın.
- Tar dosyasının içeriğini bir dizine çıkarın.
- Çıplak modül tanımlayıcılarını çözümleyebilen bir geliştirme sunucusu yükleyin (Lit ekibi @web/dev-server'ı önerir)
- Bir örnek verelim
package.json
- Bir örnek verelim
- Geliştirme sunucusunu çalıştırın ve tarayıcınızı açın (
@web/dev-serverkullanıyorsanıznpx web-dev-server --node-resolve --watch --openkullanabilirsiniz)- Örnekteki
package.jsonkarakterini kullanıyorsanıznpm run servekarakterini kullanın.
- Örnekteki
3. Özel öğe tanımlama
Özel Öğeler
Web Components, 4 yerel web API'sinden oluşan bir koleksiyondur. Bunları şöyle sıralayabiliriz:
- ES Modülleri
- Özel Öğeler
- Shadow DOM
- HTML Şablonları
Sayfaya <script type="module"> ile yüklenen içe aktarma ve dışa aktarma işlemlerine sahip JavaScript modülleri oluşturmanıza olanak tanıyan ES modülleri spesifikasyonunu zaten kullanmışsınızdır.
Özel öğe tanımlama
Özel Öğeler spesifikasyonu, kullanıcıların JavaScript kullanarak kendi HTML öğelerini tanımlamasına olanak tanır. Adlar, yerel tarayıcı öğelerinden ayırt edilebilmeleri için tire (-) içermelidir. index.js dosyasını temizleyin ve özel bir öğe sınıfı tanımlayın:
index.js
class RatingElement extends HTMLElement {}
customElements.define('rating-element', RatingElement);
Özel öğe, HTMLElement öğesini genişleten bir sınıfın tireli bir etiket adıyla ilişkilendirilmesiyle tanımlanır. customElements.define çağrısı, tarayıcıya RatingElement sınıfını ‘rating-element' tagName'i ile ilişkilendirmesini söyler. Bu durumda, dokümanınızdaki <rating-element> adlı her öğe bu sınıfla ilişkilendirilir.
Doküman gövdesine bir <rating-element> yerleştirin ve neyin oluşturulduğunu görün.
index.html
<body>
<rating-element></rating-element>
</body>
Çıkışa baktığınızda hiçbir şeyin oluşturulmadığını görürsünüz. Tarayıcıya <rating-element> öğesinin nasıl oluşturulacağını söylemediğiniz için bu beklenen bir durumdur. Chrome Dev Araçları'ndaki <rating-element> öğe seçiciyi belirleyip konsolda şu kodu çağırarak özel öğe tanımının başarılı olduğunu doğrulayabilirsiniz:
$0.constructor
Bu komutun çıkışı şu şekilde olmalıdır:
class RatingElement extends HTMLElement {}
Özel Öğelerin Yaşam Döngüsü
Özel öğeler, bir dizi yaşam döngüsü kancasıyla birlikte gelir. Bunları şöyle sıralayabiliriz:
constructorconnectedCallbackdisconnectedCallbackattributeChangedCallbackadoptedCallback
constructor, öğe ilk oluşturulduğunda (ör. document.createElement(‘rating-element') veya new RatingElement() çağrılarak) çağrılır. Oluşturucu, öğenizi ayarlamak için iyi bir yerdir ancak öğe "başlatma" performansıyla ilgili nedenlerden dolayı oluşturucuda DOM manipülasyonları yapmak genellikle kötü bir uygulama olarak kabul edilir.
Özel öğe DOM'ye eklendiğinde connectedCallback çağrılır. Genellikle ilk DOM manipülasyonları burada gerçekleşir.
disconnectedCallback, özel öğe DOM'dan kaldırıldıktan sonra çağrılır.
Kullanıcı tarafından belirtilen özelliklerden herhangi biri değiştiğinde attributeChangedCallback(attrName, oldValue, newValue) çağrılır.
adoptedCallback, özel öğe başka bir documentFragment öğesinden adoptNode aracılığıyla ana dokümana aktarıldığında (ör. HTMLTemplateElement) çağrılır.
DOM'u oluştur
Şimdi özel öğeye dönün ve bununla bazı DOM'ları ilişkilendirin. Öğe DOM'a eklendiğinde içeriğini ayarlayın:
index.js
class RatingElement extends HTMLElement {
constructor() {
super();
this.rating = 0;
}
connectedCallback() {
this.innerHTML = `
<style>
rating-element {
display: inline-flex;
align-items: center;
}
rating-element button {
background: transparent;
border: none;
cursor: pointer;
}
</style>
<button class="thumb_down" >
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button class="thumb_up">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>
`;
}
}
customElements.define('rating-element', RatingElement);
constructor içinde, öğede rating adlı bir örnek özelliği depolarsınız. connectedCallback içinde, mevcut puanı göstermek için <rating-element> öğesine DOM alt öğeleri ekleyerek beğenme ve beğenmeme düğmelerini kullanırsınız.
4. Shadow DOM
Neden gölge DOM?
Önceki adımda, eklediğiniz stil etiketindeki seçicilerin sayfadaki tüm derecelendirme öğelerini ve tüm düğmeleri seçtiğini fark edeceksiniz. Bu durum, stillerin öğeden sızmasına ve stil vermek istemediğiniz diğer düğümlerin seçilmesine neden olabilir. Ayrıca, bu özel öğenin dışındaki diğer stiller, özel öğenizin içindeki düğümleri istemeden şekillendirebilir. Örneğin, ana belgenin baş kısmına bir stil etiketi yerleştirmeyi deneyin:
index.html
<!DOCTYPE html>
<html>
<head>
<script src="./index.js" type="module"></script>
<style>
span {
border: 1px solid red;
}
</style>
</head>
<body>
<rating-element></rating-element>
</body>
</html>
Çıkışınızda, derecelendirme aralığının etrafında kırmızı bir kenarlık kutusu olmalıdır. Bu önemsiz bir durumdur ancak DOM kapsüllemenin olmaması, daha karmaşık uygulamalarda daha büyük sorunlara yol açabilir. Bu noktada gölge DOM devreye girer.
Gölge kökü ekleme
Öğeye bir gölge kökü ekleyin ve DOM'u bu kök içinde oluşturun:
index.js
class RatingElement extends HTMLElement {
constructor() {
super();
this.rating = 0;
}
connectedCallback() {
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = `
<style>
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
</style>
<button class="thumb_down" >
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button class="thumb_up">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>
`;
}
}
customElements.define('rating-element', RatingElement);
Sayfayı yenilediğinizde, ana belgedeki stillerin artık gölge kökünün içindeki düğümleri seçemediğini fark edeceksiniz.
Bunu nasıl yaptınız? connectedCallback içinde this.attachShadow işlevini çağırarak bir öğeye gölge kökü ekleyin. open modu, gölge içeriğinin incelenebilir olduğu ve gölge kökünün this.shadowRoot üzerinden de erişilebilir olduğu anlamına gelir. Chrome inceleme aracında web bileşenine de göz atın:

Artık içerikleri barındıran genişletilebilir bir gölge kökü görmelisiniz. Bu gölge kökünün içindeki her şeye gölge DOM denir. Chrome Dev Araçları'nda derecelendirme öğesini seçip $0.children işlevini çağırdığınızda, işlevin herhangi bir alt öğe döndürmediğini görürsünüz. Bunun nedeni, gölge DOM'un doğrudan alt öğelerle aynı DOM ağacının bir parçası olarak değil, gölge ağacı olarak kabul edilmesidir.
Light DOM
Bir deneme: <rating-element> öğesinin doğrudan alt öğesi olarak bir düğüm ekleyin:
index.html
<rating-element>
<div>
This is the light DOM!
</div>
</rating-element>
Sayfayı yenilediğinizde, bu özel öğenin Light DOM'undaki yeni DOM düğümünün sayfada görünmediğini görürsünüz. Bunun nedeni, gölge DOM'un <slot> öğeleri aracılığıyla ışık DOM düğümlerinin gölge DOM'a nasıl yansıtılacağını kontrol etmeye yönelik özelliklere sahip olmasıdır.
5. HTML Şablonları
Şablonları neden kullanmalısınız?
innerHTML ve temizlenmemiş şablon hazır dizelerini kullanmak, komut dosyası yerleştirme ile ilgili güvenlik sorunlarına neden olabilir. Geçmişte kullanılan yöntemler arasında DocumentFragment kullanmak da vardı ancak bu yöntemler, şablonlar tanımlandığında resimlerin yüklenmesi ve komut dosyalarının çalıştırılması gibi başka sorunlara da yol açıyor ve yeniden kullanılabilirlik açısından engeller oluşturuyordu. Bu noktada <template> öğesi devreye girer. Şablonlar, inert DOM, düğümleri klonlamak için yüksek performanslı bir yöntem ve yeniden kullanılabilir şablon oluşturma sağlar.
Şablonları kullanma
Ardından, bileşeni HTML şablonlarını kullanacak şekilde geçirin:
index.html
<body>
<template id="rating-element-template">
<style>
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
</style>
<button class="thumb_down" >
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating"></span>
<button class="thumb_up">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>
</template>
<rating-element>
<div>
This is the light DOM!
</div>
</rating-element>
</body>
Burada, DOM içeriğini ana dokümanın DOM'undaki bir şablon etiketine taşıdınız. Şimdi özel öğe tanımını yeniden düzenleyin:
index.js
class RatingElement extends HTMLElement {
constructor() {
super();
this.rating = 0;
}
connectedCallback() {
const shadowRoot = this.attachShadow({mode: 'open'});
const templateContent = document.getElementById('rating-element-template').content;
const clonedContent = templateContent.cloneNode(true);
shadowRoot.appendChild(clonedContent);
this.shadowRoot.querySelector('.rating').innerText = this.rating;
}
}
customElements.define('rating-element', RatingElement);
Bu şablon öğesini kullanmak için şablonu sorgular, içeriğini alır ve templateContent.cloneNode ile bu düğümleri klonlarsınız. Burada true bağımsız değişkeni derin bir klonlama işlemi gerçekleştirir. Ardından, DOM'u verilerle başlatırsınız.
Tebrikler, artık bir web bileşeniniz var. Maalesef henüz hiçbir şey yapmıyor. Bu nedenle, sonraki adımda biraz işlevsellik ekleyin.
6. İşlev Ekleme
Mülk Bağlamaları
Şu anda, derecelendirme öğesindeki derecelendirmeyi ayarlamanın tek yolu öğeyi oluşturmak, nesnede rating özelliğini ayarlamak ve ardından sayfaya yerleştirmektir. Ancak yerel HTML öğeleri genellikle bu şekilde çalışmaz. Yerel HTML öğeleri, hem özellik hem de özellik değişiklikleriyle güncellenir.
Aşağıdaki satırları ekleyerek özel öğenin, rating özelliği değiştiğinde görünümü güncellemesini sağlayın:
index.js
constructor() {
super();
this._rating = 0;
}
set rating(value) {
this._rating = value;
if (!this.shadowRoot) {
return;
}
const ratingEl = this.shadowRoot.querySelector('.rating');
if (ratingEl) {
ratingEl.innerText = this._rating;
}
}
get rating() {
return this._rating;
}
Puan özelliği için bir belirleyici ve alıcı ekleyip varsa puan öğesinin metnini güncellersiniz. Yani, öğede derecelendirme özelliğini ayarlarsanız görünüm güncellenir. Geliştirici Araçları konsolunuzda hızlı bir test yapın.
Özellik Bağlamaları
Şimdi, özellik değiştiğinde görünümü güncelleyin. Bu, <input value="newValue"> ayarlandığında görünümünü güncelleyen bir girişe benzer. Neyse ki Web Bileşeni yaşam döngüsü attributeChangedCallback içerir. Aşağıdaki satırları ekleyerek derecelendirmeyi güncelleyin:
index.js
static get observedAttributes() {
return ['rating'];
}
attributeChangedCallback(attributeName, oldValue, newValue) {
if (attributeName === 'rating') {
const newRating = Number(newValue);
this.rating = newRating;
}
}
attributeChangedCallback tetiklenmesi için RatingElement.observedAttributes which defines the attributes to be observed for changes için statik bir alıcı ayarlamanız gerekir. Ardından, derecelendirmeyi DOM'da bildirimsel olarak ayarlarsınız. Deneyin:
index.html
<rating-element rating="5"></rating-element>
Derecelendirme artık bildirimli olarak güncellenmelidir.
Düğme İşlevselliği
Şimdi tek eksik düğme işlevselliği. Bu bileşenin davranışı, kullanıcının tek bir olumlu veya olumsuz oy değerlendirmesi vermesine ve kullanıcıya görsel geri bildirimde bulunmasına olanak tanımalıdır. Bunu bazı etkinlik dinleyicileri ve yansıtıcı bir özellik ile uygulayabilirsiniz. Ancak öncelikle aşağıdaki satırları ekleyerek stilleri güncelleyin ve görsel geri bildirim sağlayın:
index.html
<style>
...
:host([vote=up]) .thumb_up {
fill: green;
}
:host([vote=down]) .thumb_down {
fill: red;
}
</style>
Gölge DOM'da :host seçici, gölge kökünün bağlı olduğu düğümü veya özel öğeyi ifade eder. Bu durumda, vote özelliği "up" ise beğeni düğmesi yeşile döner ancak vote özelliği "down", then it will turn the thumb-down button red ise düğme yeşile dönmez. Şimdi, rating özelliğini uyguladığınız şekilde vote için yansıtıcı bir özellik / nitelik oluşturarak bu mantığı uygulayın. Özellik ayarlayıcı ve alıcı ile başlayın:
index.js
constructor() {
super();
this._rating = 0;
this._vote = null;
}
set vote(newValue) {
const oldValue = this._vote;
if (newValue === oldValue) {
return;
}
if (newValue === 'up') {
if (oldValue === 'down') {
this.rating += 2;
} else {
this.rating += 1;
}
} else if (newValue === 'down') {
if (oldValue === 'up') {
this.rating -= 2;
} else {
this.rating -= 1;
}
}
this._vote = newValue;
this.setAttribute('vote', newValue);
}
get vote() {
return this._vote;
}
_vote örnek özelliğini constructor içinde null ile başlatır ve ayarlayıcıda yeni değerin farklı olup olmadığını kontrol edersiniz. Bu durumda, derecelendirmeyi buna göre ayarlarsınız ve en önemlisi, vote özelliğini this.setAttribute ile birlikte ana makineye geri yansıtırsınız.
Ardından, özellik bağlamayı ayarlayın:
index.js
static get observedAttributes() {
return ['rating', 'vote'];
}
attributeChangedCallback(attributeName, oldValue, newValue) {
if (attributeName === 'rating') {
const newRating = Number(newValue);
this.rating = newRating;
} else if (attributeName === 'vote') {
this.vote = newValue;
}
}
Bu işlem, rating özelliği bağlamada uyguladığınız işlemin aynısıdır. vote özelliğini observedAttributes özelliğine ekler ve vote özelliğini attributeChangedCallback içinde ayarlarsınız. Son olarak, düğmelere işlevsellik kazandırmak için bazı tıklama etkinliği dinleyicileri ekleyin.
index.js
constructor() {
super();
this._rating = 0;
this._vote = null;
this._boundOnUpClick = this._onUpClick.bind(this);
this._boundOnDownClick = this._onDownClick.bind(this);
}
connectedCallback() {
...
this.shadowRoot.querySelector('.thumb_up')
.addEventListener('click', this._boundOnUpClick);
this.shadowRoot.querySelector('.thumb_down')
.addEventListener('click', this._boundOnDownClick);
}
disconnectedCallback() {
this.shadowRoot.querySelector('.thumb_up')
.removeEventListener('click', this._boundOnUpClick);
this.shadowRoot.querySelector('.thumb_down')
.removeEventListener('click', this._boundOnDownClick);
}
_onUpClick() {
this.vote = 'up';
}
_onDownClick() {
this.vote = 'down';
}
constructor içinde, öğeye bazı tıklama dinleyicileri bağlar ve referansları saklarsınız. connectedCallback içinde düğmelerdeki tıklama etkinliklerini dinlersiniz. disconnectedCallback içinde bu dinleyicileri temizler ve dinleyicilerin kendilerini tıklayarak vote değerini uygun şekilde ayarlarsınız.
Tebrikler, artık tam özellikli bir web bileşeniniz var. Bazı düğmeleri tıklamayı deneyin. Şu anda JS dosyam 96 satıra, HTML dosyam ise 43 satıra ulaşıyor. Kod, bu kadar basit bir bileşen için oldukça ayrıntılı ve zorunlu. Google'ın Lit projesi tam da bu noktada devreye girer.
7. Lit-html
Kod Kontrol Noktası
Neden lit-html?
Öncelikle <template> etiketi kullanışlı ve yüksek performanslıdır ancak bileşenin mantığıyla birlikte paketlenmediği için şablonun mantığın geri kalanıyla birlikte dağıtılması zordur. Ayrıca, şablon öğelerinin kullanılma şekli zorunlu kodlamaya yol açar. Bu da çoğu durumda, bildirimsel kodlama kalıplarına kıyasla daha az okunabilir kodlara neden olur.
Bu noktada lit-html devreye girer. Lit HTML, Lit'in oluşturma sistemidir. Bu sistem, JavaScript'te HTML şablonları yazmanıza, ardından DOM'u oluşturmak ve güncellemek için bu şablonları verilerle birlikte etkili bir şekilde oluşturup yeniden oluşturmanıza olanak tanır. Bu kitaplık, popüler JSX ve VDOM kitaplıklarına benzer ancak tarayıcıda yerel olarak ve birçok durumda çok daha verimli çalışır.
Lit HTML'yi kullanma
Ardından, Tagged Template Literals kullanan Lit şablonunu kullanmak için yerel Web Component rating-element öğesini taşıyın. Bu öğe, şablon dizelerini özel söz dizimiyle bağımsız değişken olarak alan işlevlerdir. Lit, hızlı oluşturma sağlamak ve güvenlik için bazı temizleme özellikleri sunmak üzere arka planda şablon öğelerini kullanır. index.html içindeki <template> öğesini, web bileşenine render() yöntemi ekleyerek Lit şablonuna taşıyarak başlayın:
index.js
// Dont forget to import from Lit!
import {render, html} from 'lit';
class RatingElement extends HTMLElement {
...
render() {
if (!this.shadowRoot) {
return;
}
const template = html`
<style>
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
:host([vote=up]) .thumb_up {
fill: green;
}
:host([vote=down]) .thumb_down {
fill: red;
}
</style>
<button class="thumb_down">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button class="thumb_up">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>`;
render(template, this.shadowRoot);
}
}
Şablonunuzu index.html bölümünden de silebilirsiniz. Bu oluşturma yönteminde template adlı bir değişken tanımlar ve html etiketli şablon değişmez işlevini çağırırsınız. Ayrıca, ${...} öğesinin şablon değişmez değer interpolasyon söz dizimini kullanarak span.rating öğesinde basit bir veri bağlama işlemi gerçekleştirdiğinizi de fark edeceksiniz. Bu durumda, söz konusu düğümü zorunlu olarak güncellemeniz gerekmez. Ayrıca, şablonu gölge köküne eşzamanlı olarak işleyen lit render yöntemini çağırırsınız.
Bildirim Temelli Söz Dizimine Geçiş
<template> öğesini kaldırdığınıza göre, kodu yeniden düzenleyerek yeni tanımlanan render yöntemini çağırın. Dinleyici kodunu temizlemek için Lit'in etkinlik işleyici bağlamasını kullanarak başlayabilirsiniz:
index.js
<button
class="thumb_down"
@click=${() => {this.vote = 'down'}}>
...
<button
class="thumb_up"
@click=${() => {this.vote = 'up'}}>
Lit şablonları, @EVENT_NAME bağlama söz dizimiyle bir düğüme etkinlik dinleyicisi ekleyebilir. Bu durumda, bu düğmeler her tıklandığında vote özelliğini güncellersiniz.
Ardından, constructor ve connectedCallback ile disconnectedCallback içindeki etkinlik işleyici başlatma kodunu temizleyin:
index.js
constructor() {
super();
this._rating = 0;
this._vote = null;
}
connectedCallback() {
this.attachShadow({mode: 'open'});
this.render();
}
// remove disonnectedCallback and _onUpClick and _onDownClick
Tıklama işleyici mantığını üç geri çağırmanın tümünden kaldırabildiniz ve hatta disconnectedCallback öğesini tamamen kaldırabildiniz. Ayrıca, connectedCallback üzerindeki tüm DOM başlatma kodunu kaldırarak çok daha zarif görünmesini sağladınız. Bu, _onUpClick ve _onDownClick dinleyici yöntemlerinden de kurtulabileceğiniz anlamına gelir.
Son olarak, mülkler veya özellikler değiştiğinde DOM'un güncellenebilmesi için mülk ayarlayıcıları render yöntemini kullanacak şekilde güncelleyin:
index.js
set rating(value) {
this._rating = value;
this.render();
}
...
set vote(newValue) {
const oldValue = this._vote;
if (newValue === oldValue) {
return;
}
if (newValue === 'up') {
if (oldValue === 'down') {
this.rating += 2;
} else {
this.rating += 1;
}
} else if (newValue === 'down') {
if (oldValue === 'up') {
this.rating -= 2;
} else {
this.rating -= 1;
}
}
this._vote = newValue;
this.setAttribute('vote', newValue);
// add render method
this.render();
}
Burada, DOM güncelleme mantığını rating belirleyiciden kaldırdınız ve vote belirleyiciden render belirleyicisine bir çağrı eklediniz. Artık bağlamaların ve etkinlik işleyicilerinin nereye uygulandığını görebildiğiniz için şablon çok daha okunabilir.
Sayfayı yenilediğinizde, beğenme düğmesi çalışır duruma gelir. Bu düğmeye basıldığında aşağıdaki gibi görünür.

8. LitElement
Neden LitElement?
Kodla ilgili bazı sorunlar devam ediyor. İlk olarak, vote özelliğini veya özelliğini değiştirirseniz rating özelliği değişebilir. Bu da render işlevinin iki kez çağrılmasına neden olur. Render işlevinin tekrar tekrar çağrılması esasen işlemsiz ve verimli olmasına rağmen, JavaScript sanal makinesi bu işlevi iki kez eşzamanlı olarak çağırmak için zaman harcamaya devam ediyor. İkincisi, çok fazla standart kod gerektirdiğinden yeni özellikler ve nitelikler eklemek sıkıcıdır. Bu noktada LitElement devreye girer.
LitElement, çerçeveler ve ortamlar arasında kullanılabilen hızlı ve hafif web bileşenleri oluşturmak için Lit'in temel sınıfıdır. Ardından, uygulamayı değiştirerek LitElement'nın rating-element'da bizim için neler yapabileceğine göz atın.
LitElement'i kullanma
LitElement temel sınıfını lit paketinden içe aktarıp alt sınıf oluşturarak başlayın:
index.js
import {LitElement, html, css} from 'lit';
class RatingElement extends LitElement {
// remove connectedCallback()
...
rating-element için yeni temel sınıf olan LitElement sınıfını içe aktarırsınız. Ardından html içe aktarma işlemini yaparsınız ve son olarak css ile CSS matematik, şablon oluşturma ve diğer özellikler için CSS etiketli şablon değişmezlerini tanımlayabiliriz.
Ardından, stilleri oluşturma yönteminden Lit'in statik stil sayfasına taşıyın:
index.js
class RatingElement extends LitElement {
static get styles() {
return css`
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
:host([vote=up]) .thumb_up {
fill: green;
}
:host([vote=down]) .thumb_down {
fill: red;
}
`;
}
...
Lit'teki çoğu stil burada yer alır. Lit, bu stilleri alır ve daha hızlı oluşturma süreleri sağlamak için Constructable Stylesheets gibi tarayıcı özelliklerini kullanır. Gerekirse eski tarayıcılarda Web Components polyfill'i de kullanır.
Yaşam döngüsü
Lit, yerel Web Bileşeni geri çağırmalarının üzerinde bir dizi oluşturma yaşam döngüsü geri çağırma yöntemi sunar. Bu geri çağırmalar, bildirilen Lit özellikleri değiştirildiğinde tetiklenir.
Bu özelliği kullanmak için hangi özelliklerin oluşturma yaşam döngüsünü tetikleyeceğini statik olarak bildirmeniz gerekir.
index.js
static get properties() {
return {
rating: {
type: Number,
},
vote: {
type: String,
reflect: true,
}
};
}
// remove observedAttributes() and attributeChangedCallback()
// remove set rating() get rating()
Burada, rating ve vote özelliklerinin LitElement oluşturma yaşam döngüsünü tetikleyeceğini ve dize özelliklerini özelliklere dönüştürmek için kullanılacak türleri tanımlarsınız.
<user-profile .name=${this.user.name} .age=${this.user.age}>
${this.user.family.map(member => html`
<family-member
.name=${member.name}
.relation=${member.relation}>
</family-member>`)}
</user-profile>
Ayrıca, reflect özelliğindeki vote işareti, vote belirleyicide manuel olarak tetiklediğiniz ana makine öğesinin vote özelliğini otomatik olarak günceller.
Artık statik özellikler bloğunuz olduğuna göre, tüm özellik ve mülk oluşturma güncelleme mantığını kaldırabilirsiniz. Bu, aşağıdaki yöntemleri kaldırabileceğiniz anlamına gelir:
connectedCallbackobservedAttributesattributeChangedCallbackrating(setter ve getter)vote(belirleyiciler ve alıcılar ancak belirleyicideki değişiklik mantığını korur)
Aşağıdakileri koruyabilir ve yeni bir willUpdate yaşam döngüsü yöntemi ekleyebilirsiniz:constructor
index.js
constructor() {
super();
this.rating = 0;
this.vote = null;
}
willUpdate(changedProps) {
if (changedProps.has('vote')) {
const newValue = this.vote;
const oldValue = changedProps.get('vote');
if (newValue === 'up') {
if (oldValue === 'down') {
this.rating += 2;
} else {
this.rating += 1;
}
} else if (newValue === 'down') {
if (oldValue === 'up') {
this.rating -= 2;
} else {
this.rating -= 1;
}
}
}
}
// remove set vote() and get vote()
Burada, rating ve vote öğelerini başlatmanız ve vote belirleyici mantığını willUpdate yaşam döngüsü yöntemine taşımanız yeterlidir. LitElement, özellik değişikliklerini toplu olarak işleyip oluşturmayı eşzamansız hale getirdiğinden, güncellenen herhangi bir özellik her değiştirildiğinde willUpdate yöntemi render'den önce çağrılır. willUpdate içindeki tepkisel özelliklerde (ör. this.rating) yapılan değişiklikler gereksiz render yaşam döngüsü çağrılarını tetiklemez.
Son olarak, render, Lit şablonu döndürmemizi gerektiren bir LitElement yaşam döngüsü yöntemidir:
index.js
render() {
return html`
<button
class="thumb_down"
@click=${() => {this.vote = 'down'}}>
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button
class="thumb_up"
@click=${() => {this.vote = 'up'}}>
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>`;
}
Artık gölge kökünü kontrol etmeniz ve daha önce 'lit' paketinden içe aktarılan render fonksiyonunu çağırmanız gerekmez.
Öğeniz artık önizlemede oluşturulmalıdır. Öğeyi tıklayın.
9. Tebrikler
Tebrikler! Sıfırdan bir web bileşeni oluşturup LitElement'e dönüştürmeyi başardınız.
Lit, çok küçük (< 5 kb küçültülmüş + gzip'lenmiş), çok hızlı ve kodlaması gerçekten eğlenceli bir kütüphanedir. Diğer çerçeveler tarafından kullanılacak bileşenler oluşturabilir veya bu çerçeveyle tam teşekküllü uygulamalar geliştirebilirsiniz.
Artık web bileşeninin ne olduğunu, nasıl oluşturulacağını ve Lit'in bunları oluşturmayı nasıl kolaylaştırdığını biliyorsunuz.
Kod Kontrol Noktası
Son kodunuzu bizimkiyle karşılaştırmak ister misiniz? Karşılaştırmayı buradan yapabilirsiniz.
Yapabilecekleriniz
Diğer codelab'lere göz atın.
- React geliştiricileri için Lit
- lit-element ile Brick Viewer oluşturma
- lit-element ile Hikayeler bileşeni oluşturma
Daha fazla bilgi
- Lit etkileşimli eğitimi
- The Lit Docs
- Open Web Components: Topluluk tarafından yönetilen bir rehberlik ve araç topluluğu
- WebComponents.dev: Bilinen tüm çerçevelerde bir web bileşeni oluşturun
Topluluk
- Lit and Friends Slack: En büyük Web Bileşenleri topluluğu
- Twitter'da@buildWithLit: Lit'i geliştiren ekibin Twitter hesabı
- Web Components SF: San Francisco'da Web Components ile ilgili bir buluşma