1. Giriş
Son Güncelleme: 10.08.2021
Web Bileşenleri
Web Bileşenleri, web sayfaları ve web uygulamalarında kullanılacak yeni özel, yeniden kullanılabilir, kapsüllenmiş HTML etiketleri oluşturmanızı sağlayan web platformu API'leri kümesidir. Web Bileşeni standartlarını temel alan ö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.
Edebiyat nedir?
Lit, herhangi bir çerçevede çalışan veya hiçbir çerçeve olmadan çalışan hızlı ve hafif web bileşenleri oluşturmaya yönelik basit bir kitaplıktır. Lit'i kullanarak paylaşılabilir bileşenler, uygulamalar, tasarım sistemleri ve daha fazlasını oluşturabilirsiniz.
Lit; mülkleri, özellikleri ve oluşturma gibi yaygın Web Bileşenleri görevlerini basitleştirmek için API'ler sunar.
Neler öğreneceksiniz?
- Web Bileşeni nedir?
- Web Bileşenleri kavramları
- Web Bileşeni oluşturma
- lit-html ve LitElement nedir?
- Lit'in web bileşeni üzerinde yaptığı işlemler
Oluşturacaklarınız
- vanilya, 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 ve çoklu dolgular Microsoft Internet Explorer 11 ve Chrome olmayan Microsoft Edge için kullanılabilir.
- HTML, CSS, JavaScript ve Chrome Geliştirici Araçları hakkında bilgi sahibi olmak.
2. Kurulum ve Playground'u keşfediyor
Koda erişme
Codelab boyunca Edebiyat oyun alanına şu şekilde bağlantılar verilecektir:
Oyun alanı, tamamen tarayıcınızda çalışan bir kod korumalı alanıdır. TypeScript ve JavaScript dosyalarını derleyip çalıştırabilir, ayrıca düğüm modüllerine yapılan içe aktarmaları otomatik olarak çözümleyebilir. ör.
// before
import './my-file.js';
import 'lit';
// after
import './my-file.js';
import 'https://unpkg.com/lit?module';
Bu kontrol noktalarını başlangıç noktaları olarak kullanarak eğitici içeriğin tamamını Edebiyat oyun alanında uygulayabilirsiniz. VS Code kullanıyorsanız bu kontrol noktalarını herhangi bir adımın başlangıç kodunu indirmek için kullanabilir ve ayrıca bunları çalışmanızı kontrol etmek için de kullanabilirsiniz.
Işıklı oyun alanının kullanıcı arayüzünü keşfetmek
Lit Gaming kullanıcı arayüzü ekran görüntüsünde, bu codelab'de kullanacağınız bölümler vurgulanmaktadır.
- Dosya seçici. Artı düğmesine dikkat edin...
- Dosya düzenleyici.
- Kod önizlemesi.
- Yeniden yükle düğmesi.
- İndir düğmesi.
VS Kod kurulumu (Gelişmiş)
Bu VS Code kurulumunu kullanmanın avantajları şunlardır:
- Şablon türü kontrolü
- Şablon zekası ve otomatik tamamlama
NPM, VS Code (lit-plugin eklentisiyle) yüklüyse ve bu ortamı nasıl kullanacağınızı biliyorsanız, aşağıdakileri yaparak bu projeleri indirip başlatmanız yeterlidir:
- İndir düğmesine basın
- tar dosyasının içeriğini bir dizine çıkarın
- Yalın modül tanımlayıcıları çözümleyebilen bir geliştirici sunucusu yükleyin (Lit ekibi @web/dev-server'ı önerir)
- Örnek
package.json
- Örnek
- Geliştirici sunucusunu çalıştırın ve tarayıcınızı açın (
@web/dev-server
kullanıyorsanıznpx web-dev-server --node-resolve --watch --open
kullanabilirsiniz)package.json
örneğini kullanıyorsanıznpm run serve
kullanın.
3. Özel Öğe Tanımlayın
Özel Öğeler
Web Bileşenleri, 4 yerel web API'sinden oluşan bir koleksiyondur. Bunlar:
- ES Modülleri
- Özel Öğeler
- Gölge DOM
- HTML Şablonları
İçe ve dışa aktarma işlemlerine sahip, <script type="module">
ile sayfaya yüklenen JavaScript modülleri oluşturmanıza olanak tanıyan ES modülleri spesifikasyonunu daha önce kullandınız.
Özel Öğe Tanımlama
Custom Elements spesifikasyonu, kullanıcıların JavaScript kullanarak kendi HTML öğelerini tanımlamalarına olanak tanır. Adlar, yerel tarayıcı öğelerinden ayırt edilebilmeleri için kısa çizgi (-
) içermelidir. index.js
dosyasını temizleyin ve bir özel öğ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 kısa çizgili bir etiket adıyla ilişkilendirilmesiyle tanımlanır. customElements.define
çağrısı, tarayıcıya RatingElement
sınıfını tagName ‘rating-element'
ile ilişkilendirmesini bildirir. Bu durum, dokümanınızda <rating-element>
adlı her öğenin bu sınıfla ilişkilendirileceği anlamına gelir.
Doküman gövdesine <rating-element>
yerleştirin ve nelerin 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ı bildirmediğiniz için bu, beklenen bir durumdur. Chrome Geliştirici Araçları'nda <rating-element>
öğesini seçerek özel öğe tanımının başarılı olduğunu onaylayabilirsiniz öğe seçicide çalışır ve konsolda şunları çağırır:
$0.constructor
Bu kod aşağıdaki sonucu verir:
class RatingElement extends HTMLElement {}
Özel Öğe Yaşam Döngüsü
Özel Öğeler, bir dizi yaşam döngüsü kancasıyla birlikte gelir. Bunlar:
constructor
connectedCallback
disconnectedCallback
attributeChangedCallback
adoptedCallback
constructor
, öğe ilk oluşturulduğunda (örneğin, document.createElement(‘rating-element')
veya new RatingElement()
) çağrılır. Oluşturucu, öğenizi ayarlamak için iyi bir yerdir ancak "boot-up" öğesi için oluşturucuda DOM değiştirmeleri yapmak genellikle kötü bir uygulama olarak kabul edilir performansa neden olabilir.
Özel öğe DOM'ye eklendiğinde connectedCallback
çağrılır. İlk DOM manipülasyonları genellikle bu aşamada gerçekleşir.
disconnectedCallback
, özel öğe DOM'den kaldırıldıktan sonra çağrılır.
attributeChangedCallback(attrName, oldValue, newValue)
, kullanıcı tarafından belirtilen özelliklerden herhangi biri değiştiğinde çağrılır.
Özel öğe, adoptNode
aracılığıyla ana dokümana (ör. HTMLTemplateElement
içinde) başka bir documentFragment
öğesi uygulandığında adoptedCallback
çağrılır.
DOM oluşturma
Şimdi özel öğeye geri dönün ve bununla bir DOM ilişkilendirin. DOM'ye eklendiğinde öğenin 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
öğesinde, öğe üzerinde rating
adlı bir örnek özelliği depoluyorsunuz. connectedCallback
içinde, beğenme ve beğenmeme düğmeleriyle birlikte geçerli puanı görüntülemek için <rating-element>
öğesine DOM alt öğeleri eklersiniz.
4. Gölge DOM
Neden Gölge DOM?
Önceki adımda, eklediğiniz stil etiketindeki seçicilerin sayfadaki herhangi bir derecelendirme öğesini ve herhangi bir düğmeyi seçtiğini göreceksiniz. Bu, stillerin öğenin dışına sızmasına ve stilini belirlemeyi düşünmediğiniz başka düğümler seçmesine neden olabilir. Ayrıca, bu özel öğenin dışındaki diğer stiller yanlışlıkla özel öğenizin içindeki düğümlerin stilini belirleyebilir. Örneğin, ana dokümanın başına 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ızın, derecelendirme aralığının çevresinde kırmızı bir kenarlık kutusu olması gerekir. Bu sıradan bir durum olsa da DOM kapsüllemenin eksik olması, daha karmaşık uygulamalarda daha büyük sorunlara yol açabilir. İşte Gölge DOM burada devreye girer.
Gölge Kökü Ekleme
Öğeye bir Gölge Kökü ekleyin ve DOM'yi bu kökün 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 dokümandaki stillerin artık Gölge Kökü içindeki düğümleri seçemediğini fark edeceksiniz.
Bunu nasıl yaptınız? connectedCallback
öğesinde, bir öğeye gölge kökü ekleyen this.attachShadow
adını verdiniz. open
modu, gölge içeriğinin incelenebileceği anlamına gelir ve gölge kökünün this.shadowRoot
üzerinden de erişilebilir olmasını sağlar. Chrome denetleyicisindeki Web Bileşeni'ne de bakın:
Şimdi, içeriği barındıran genişletilebilir bir gölge kökü görmeniz gerekir. Gölge kökünün içindeki her şeye Gölge DOM denir. Chrome Geliştirici Araçları'nda derecelendirme öğesini seçer ve $0.children
yöntemini çağırırsanız alt öğe döndürmediğini fark edersiniz. Bunun nedeni, Gölge DOM'nin doğrudan alt yayıncılarla aynı DOM ağacının bir parçası olarak değil, Gölge Ağacı'nın bir parçası olarak kabul edilmesidir.
Hafif DOM
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'sindeki bu yeni DOM düğümünün sayfada görünmediğini görürsünüz. Bunun nedeni Gölge DOM'un, Işık DOM düğümlerinin <slot>
öğeleri aracılığıyla gölge alanına nasıl yansıtılacağını kontrol eden özelliklere sahip olmasıdır.
5. HTML Şablonları
Neden Şablonlar?
innerHTML
ve şablon sabit değer dizelerinin temizleme yapılmadan kullanılması, komut dosyası yerleştirmeyle ilgili güvenlik sorunlarına neden olabilir. Geçmişteki yöntemler DocumentFragment
'ların kullanılmasını içeriyordu. Ancak bu yöntemler arasında resimlerin yüklenmesi, şablonların tanımlanması sırasında çalıştırılması ve yeniden kullanılabilirliğin önünde engellerin oluşması gibi başka sorunlar da yer alıyordu. <template>
öğesi burada devreye girer. Şablonlar, düğümleri klonlamak için yüksek performanslı bir yöntem olan inert DOM ve yeniden kullanılabilir şablon oluşturur.
Şablonları kullanma
Daha sonra, bileşeni HTML Şablonlarını kullanacak şekilde değiştirin:
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'sindeki 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 sorgulayıp içeriğini almanız ve bu düğümleri templateContent.cloneNode
ile klonlamanız gerekir. Burada true
bağımsız değişkeni derin bir klonlama gerçekleştirir. Daha sonra dom'u verilerle ilk kullanıma hazırlarsınız.
Tebrikler, artık bir Web Bileşeniniz var! Maalesef henüz hiçbir şey yapmıyor. Bu yüzden, biraz daha işlevsellik ekleyin.
6. İşlev Ekleme
Mülk Bağlantıları
Şu anda, derecelendirme öğesinde derecelendirmeyi ayarlamanın tek yolu öğeyi oluşturmak, nesnede rating
özelliğini ayarlamak ve ardından sayfaya yerleştirmektir. Maalesef yerel HTML öğelerinin çalışma biçimi bu değildir. Yerel HTML öğeleri, hem özellik hem de özellik değişiklikleriyle güncellenme eğilimindedir.
Aşağıdaki satırları ekleyerek, rating
özelliği değiştiğinde özel öğenin 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;
}
Derecelendirme özelliği için bir belirleyici ve alıcı eklersiniz, ardından varsa derecelendirme öğesinin metnini güncellersiniz. Bu, öğede derecelendirme özelliğini ayarlarsanız görünümün güncelleneceği anlamına gelir; Geliştirici Araçları konsolunuzda kısa bir test yapın.
Özellik Bağlamaları
Şimdi, özellik değiştiğinde görünümü güncelleyin; bu, <input value="newValue">
olarak ayarlandığında görünümü 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 puanı güncelleyin:
index.js
static get observedAttributes() {
return ['rating'];
}
attributeChangedCallback(attributeName, oldValue, newValue) {
if (attributeName === 'rating') {
const newRating = Number(newValue);
this.rating = newRating;
}
}
attributeChangedCallback
öğesinin tetiklenmesi amacıyla RatingElement.observedAttributes which defines the attributes to be observed for changes
için statik alıcı ayarlamanız gerekir. Daha sonra, derecelendirmeyi DOM'de bildirimli şekilde ayarlarsınız. Bir deneyin:
index.html
<rating-element rating="5"></rating-element>
Puan artık beyan verecek şekilde güncellenecek.
Düğme İşlevselliği
Eksik olan tek şey düğme işlevi. Bu bileşenin davranışı, kullanıcının tek bir olumlu veya olumsuz oy puanı vermesine ve kullanıcıya görsel geri bildirim sağlamasına izin vermelidir. Bunu bazı etkinlik işleyiciler ve yansıtma özelliği ile uygulayabilirsiniz, ancak önce aşağıdaki satırları ekleyerek stilleri görsel geri bildirim verecek şekilde güncelleyin:
index.html
<style>
...
:host([vote=up]) .thumb_up {
fill: green;
}
:host([vote=down]) .thumb_down {
fill: red;
}
</style>
Gölge DOM'da :host
seçicisi, 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ğenme düğmesi yeşile döner, vote
ise "down", then it will turn the thumb-down button red
değerine ayarlanır. Şimdi, vote
için rating
uyguladığınıza benzer bir yansıtma özelliği / özellik oluşturarak bunun mantığını uygulayın. Özellik belirleyici ve alıcıyla 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ırsınız ve belirleyicide yeni değerin farklı olup olmadığını kontrol edersiniz. Bu durumda, puanı uygun şekilde ayarlar ve daha da önemlisi vote
özelliğini, this.setAttribute
ile 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, rating
özellik bağlamasıyla uyguladığınız sürecin aynısıdır; observedAttributes
öğesine vote
ekler ve vote
özelliğini attributeChangedCallback
içinde ayarlarsınız. Şimdi son olarak, düğmelere işlev katmak için birkaç tıklama etkinliği işleyicisi 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 bazı tıklama işleyicileri öğeye bağlar ve referansları başka bir yerde tutarsınız. connectedCallback
içinde düğmelerdeki tıklama etkinliklerini dinlersiniz. disconnectedCallback
içinde bu işleyicileri temizlersiniz ve tıklama işleyiciler üzerinde de vote
öğesini uygun bir şekilde ayarlarsınız.
Tebrikler, artık tam özellikli bir Web Bileşeniniz var; bazı düğmeleri tıklamayı deneyin! Şimdi sorun, JS dosyamın 96 satıra, HTML dosyamın ise 43 satıra ulaşması ve kodun çok ayrıntılı ve böyle basit bir bileşen için şart olması. Google'ın Edebiyat projesi de bu noktada devreye giriyor.
7. Edebi HTML
Kod Kontrol Noktası
Neden lit-html?
Her şeyden önce, <template>
etiketi kullanışlı ve etkilidir, ancak bileşenin mantığına uygun bir şekilde paketlenmemiştir. Bu nedenle, şablonun mantığın geri kalanıyla dağıtılmasını zorlaştırır. Ayrıca, şablon öğelerinin kullanım biçimi, doğası gereği zorunlu koda da katkıda bulunur. Bu durum, çoğu durumda, bildirim temelli kodlama kalıplarına kıyasla kodların daha az okunmasına yol açar.
İşte burada devreye "lit-html" girilir. Lit html, JavaScript'te HTML şablonları yazmanıza, ardından DOM'yi oluşturmak ve güncellemek için bu şablonları verilerle birlikte verimli bir şekilde oluşturup yeniden oluşturmanıza olanak tanıyan, Lit'in oluşturma sistemidir. Popüler JSX ve VDOM kitaplıklarına benzer, ancak tarayıcıda yerel olarak ve çoğu durumda çok daha verimli bir şekilde çalışır.
Edebi HTML kullanma
Ardından, özel bir söz dizimiyle bağımsız değişken olarak şablon dizeleri alan işlevler olan Etiketli Şablon Değişmez Değerlerini kullanan Lit şablonunu kullanmak için yerel Web Bileşeni rating-element
'ni taşıyın. Ardından Lit, hızlı oluşturma ve güvenlik amacıyla bazı temizlik özellikleri sağlamak için arka planda şablon öğelerini kullanıyor. Web bileşenine render()
yöntemi ekleyerek index.html
içindeki <template>
öğesini bir 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
üzerinden de silebilirsiniz. Bu oluşturma yönteminde, template
adında bir değişken tanımlar ve html
etiketli şablon değişmez değer işlevini çağırırsınız. Ayrıca, ${...}
şablonun düz interpolasyon söz dizimini kullanarak span.rating
öğesi içinde basit bir veri bağlama gerçekleştirdiğinizi fark edeceksiniz. Bu, artık söz konusu düğümü zorunlu olarak güncellemeniz gerekmeyeceği anlamına gelir. Ayrıca, şablonu eşzamanlı olarak gölge kökünde oluşturan ışıklandırılmış render
yöntemini çağırırsınız.
Bildirim Temelli Söz Dizmine Geçiş
<template>
öğesini kaldırdığınıza göre, artık yeni tanımlanan render
yöntemini çağırmak için kodu yeniden düzenleyin. Dinleyici kodunu temizlemek için Lit'in etkinlik işleyici bağlamasından yararlanarak 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 dizimine sahip bir düğüme etkinlik işleyici ekleyebilir. Bu durumda, düğmeler her tıklandığında vote
özelliğini güncellersiniz.
Daha sonra, constructor
, connectedCallback
ve disconnectedCallback
alanlarındaki 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 tamamından kaldırabildiniz, hatta disconnectedCallback
öğesini tamamen kaldırdınız! Ayrıca, DOM başlatma kodunun tamamını connectedCallback
içinden kaldırarak çok daha zarif bir görünüme kavuştunuz. Bu sayede _onUpClick
ve _onDownClick
işleyici yöntemlerinden de kurtulabilirsiniz.
Son olarak, özellikler veya özellikler değiştiğinde dom'un güncellenebilmesi için özellik belirleyicileri 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, rating
seter'ından dom güncelleme mantığını kaldırdınız ve vote
setter'dan render
çağrısına eklediniz. Bağlamaların ve etkinlik işleyicilerin nerede uygulandığını artık görebildiğiniz için şablon artık çok daha okunaklı.
Sayfayı yenilediğinizde, olumlu oya basıldığında bunun gibi çalışan bir derecelendirme düğmeniz olacaktır!
8. LitElement
Neden LitElement?
Kodla ilgili bazı sorunlar devam ediyor. Öncelikle, vote
özelliğini veya özelliğini değiştirirseniz rating
özelliği de değişebilir. Bu da render
özelliğinin iki kez çağrılmasına neden olur. Tekrarlanan oluşturma çağrılarının aslında işlemsiz ve verimli olmasına rağmen, JavaScript sanal makinesi hâlâ bu işlevi iki kez eşzamanlı olarak çağırmak için zaman harcıyor. İkinci olarak, çok fazla standart kod gerektirdiğinden yeni özellik ve özellikler eklemek yorucudur. İşte LitElement
burada devreye giriyor.
LitElement
, Lit'in çerçeveler ve ortamlarda kullanılabilecek hızlı ve hafif Web Bileşenleri oluşturmaya yönelik temel sınıfıdır. Ardından, uygulamayı kullanacak şekilde değiştirerek LitElement
uygulamasının rating-element
içinde bizim için neler yapabileceğine bir göz atın.
LitElement'ı kullanma
lit
paketindeki LitElement
temel sınıfını içe veya alt sınıfa aktararak 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
içe aktarılsın. Ardından html
içe aktarmanızı saklar ve son olarak da css
. Bu işlem, CSS matematiği, şablon oluşturma ve arka planda bulunan diğer özellikler için css etiketli şablon değişmez değerlerini tanımlamamıza olanak tanır.
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;
}
`;
}
...
Edebiyatta stillerin çoğu burada bulunur. Bu stilleri alıp daha hızlı oluşturma süreleri sağlamak ve gerekirse eski tarayıcılardaki Web Bileşenleri çoklu dolgusundan geçirmek için Oluşturulabilir Stil Sayfaları gibi tarayıcı özelliklerini kullanır.
Yaşam döngüsü
Lit, yerel Web Bileşeni geri çağırmalarına ek olarak bir dizi oluşturma yaşam döngüsü geri çağırma yöntemi sunar. Bu geri çağırma işlevleri, bildirilen özellikler değiştirildiğinde tetiklenir.
Bu özelliği kullanmak için oluşturma yaşam döngüsünü hangi özelliklerin 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
öğelerinin 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ımlayacağını 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>
Buna ek olarak, vote
mülkündeki reflect
işareti, vote
belirleyicide manuel olarak tetiklediğiniz barındırma öğesinin vote
özelliğini otomatik olarak günceller.
Artık statik özellikler bloğuna sahip olduğunuza göre, tüm özellik ve özellik oluşturma mantığını kaldırabilirsiniz. Bu, aşağıdaki yöntemleri kaldırabileceğiniz anlamına gelir:
connectedCallback
observedAttributes
attributeChangedCallback
rating
(belirleyiciler ve alıcılar)vote
(belirleyiciler ve alıcılar ancak değişim mantığını belirleyiciden uzak tutun)
constructor
ve yeni bir willUpdate
yaşam döngüsü yöntemi eklersiniz:
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
uygulamalarını ilk kullanıma hazırlar ve vote
belirleyici mantığını willUpdate
yaşam döngüsü yöntemine taşırsınız. LitElement, özellik değişikliklerini toplu hale getirdiği ve oluşturmayı eşzamansız hale getirdiği için, herhangi bir güncelleme özelliği değiştirildiğinde willUpdate
yöntemi render
öncesinde çağrılır. willUpdate
ürününde reaktif ö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
işlevini çağırmanız gerekmez.
Öğeniz şimdi önizlemede oluşturulur; bir tıkla!
9. Tebrikler
Tebrikler, sıfırdan bir Web Bileşeni oluşturdunuz ve bunu bir LitElement öğesine dönüştürdünüz.
Edebiyat çok küçük (< 5 kb küçültülmüş + gzip ile sıkıştırılmış), çok hızlı ve kodlamak gerçekten eğlenceli. Bileşenlerin başka çerçeveler tarafından tüketilmesini sağlayabilir veya bunlarla tam teşekküllü uygulamalar geliştirebilirsiniz.
Artık Web Bileşeni'nin ne olduğunu, nasıl oluşturulacağını ve Lit'in bunları oluşturmayı nasıl kolaylaştırdığını biliyorsunuz.
Kod Kontrol Noktası
Nihai kodunuzu bizim kodumuzla karşılaştırarak kontrol etmek ister misiniz? Buradan karşılaştırabilirsiniz.
Sırada ne var?
Diğer codelab'lerden bazılarına göz atın.
- React Geliştiricileri için Lit
- Işık öğeli tuğla görüntüleyici derleme
- Işıklı öğe içeren bir Hikayeler Bileşeni derleme
Daha fazla bilgi
- Etkileşimli eğitim
- Edebi Belgeler
- Açık Web Bileşenleri - Topluluk tarafından yürütülen 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 - Edebiyatı yapan ekibin Twitter hesabı
- Web Bileşenleri SF: San Francisco'da Web Bileşenleri buluşması