PadziļinÄts ieskats tÄ«mekļa komponentu dzÄ«ves ciklÄ, aptverot pielÄgoto elementu izveidi, pievienoÅ”anu, atribÅ«tu izmaiÅas un atvienoÅ”anu. Uzziniet, kÄ veidot noturÄ«gas un atkÄrtoti lietojamas komponentes modernÄm tÄ«mekļa lietotnÄm.
TÄ«mekļa komponentu dzÄ«ves cikls: PielÄgoto elementu izveides un pÄrvaldÄ«bas apguve
TÄ«mekļa komponentes ir spÄcÄ«gs rÄ«ks atkÄrtoti lietojamu un iekapsulÄtu lietotÄja saskarnes elementu veidoÅ”anai modernajÄ tÄ«mekļa izstrÄdÄ. TÄ«mekļa komponentes dzÄ«ves cikla izpratne ir bÅ«tiska, lai radÄ«tu noturÄ«gas, uzturÄjamas un veiktspÄjÄ«gas lietotnes. Å is visaptveroÅ”ais ceļvedis pÄta dažÄdos tÄ«mekļa komponentes dzÄ«ves cikla posmus, sniedzot detalizÄtus paskaidrojumus un praktiskus piemÄrus, lai palÄ«dzÄtu jums apgÅ«t pielÄgoto elementu izveidi un pÄrvaldÄ«bu.
Kas ir tīmekļa komponentes?
TÄ«mekļa komponentes ir tÄ«mekļa platformas API kopums, kas ļauj jums izveidot atkÄrtoti lietojamus pielÄgotus HTML elementus ar iekapsulÄtu stilu un uzvedÄ«bu. TÄs sastÄv no trim galvenajÄm tehnoloÄ£ijÄm:
- PielÄgotie elementi (Custom Elements): Ä»auj definÄt savus HTML tagus un ar tiem saistÄ«to JavaScript loÄ£iku.
- Änu DOM (Shadow DOM): NodroÅ”ina iekapsulÄÅ”anu, izveidojot atseviŔķu DOM koku komponentei, pasargÄjot to no globÄlÄ dokumenta stiliem un skriptiem.
- HTML veidnes (HTML Templates): Ä»auj definÄt atkÄrtoti lietojamus HTML fragmentus, kurus var efektÄ«vi klonÄt un ievietot DOM.
TÄ«mekļa komponentes veicina koda atkÄrtotu izmantoÅ”anu, uzlabo uzturÄjamÄ«bu un ļauj veidot sarežģītas lietotÄja saskarnes modulÄrÄ un organizÄtÄ veidÄ. TÄs atbalsta visas lielÄkÄs pÄrlÅ«kprogrammas, un tÄs var izmantot ar jebkuru JavaScript ietvaru vai bibliotÄku, vai pat bez tiem.
Tīmekļa komponentu dzīves cikls
TÄ«mekļa komponentes dzÄ«ves cikls definÄ dažÄdos posmus, kurus pielÄgots elements iziet no tÄ izveides lÄ«dz noÅemÅ”anai no DOM. Å o posmu izpratne ļauj veikt konkrÄtas darbÄ«bas pareizajÄ laikÄ, nodroÅ”inot, ka jÅ«su komponente darbojas pareizi un efektÄ«vi.
GalvenÄs dzÄ«ves cikla metodes ir:
- constructor(): Konstruktors tiek izsaukts, kad elements tiek izveidots vai atjauninÄts. Å eit jÅ«s inicializÄjat komponentes stÄvokli un izveidojat tÄs Änu DOM (ja nepiecieÅ”ams).
- connectedCallback(): Tiek izsaukta katru reizi, kad pielÄgotais elements tiek pievienots dokumenta DOM. Å Ä« ir laba vieta, kur veikt iestatīŔanas uzdevumus, piemÄram, datu ielÄdi, notikumu klausÄ«tÄju pievienoÅ”anu vai komponentes sÄkotnÄjÄ satura renderÄÅ”anu.
- disconnectedCallback(): Tiek izsaukta katru reizi, kad pielÄgotais elements tiek atvienots no dokumenta DOM. Å eit jums vajadzÄtu atbrÄ«vot resursus, piemÄram, noÅemot notikumu klausÄ«tÄjus vai atceļot taimerus, lai novÄrstu atmiÅas noplÅ«des.
- attributeChangedCallback(name, oldValue, newValue): Tiek izsaukta katru reizi, kad kÄds no pielÄgotÄ elementa atribÅ«tiem tiek pievienots, noÅemts, atjauninÄts vai aizstÄts. Tas ļauj reaÄ£Ät uz izmaiÅÄm komponentes atribÅ«tos un atbilstoÅ”i atjauninÄt tÄs uzvedÄ«bu. Jums ir jÄnorÄda, kurus atribÅ«tus vÄlaties novÄrot, izmantojot
observedAttributes
statisko getteri. - adoptedCallback(): Tiek izsaukta katru reizi, kad pielÄgotais elements tiek pÄrvietots uz jaunu dokumentu. Tas ir svarÄ«gi, strÄdÄjot ar iframe vai pÄrvietojot elementus starp dažÄdÄm lietotnes daļÄm.
IedziļinÄÅ”anÄs katrÄ dzÄ«ves cikla metodÄ
1. constructor()
Konstruktors ir pirmÄ metode, kas tiek izsaukta, kad tiek izveidots jauns jÅ«su pielÄgotÄ elementa eksemplÄrs. TÄ ir ideÄla vieta, kur:
- InicializÄt komponentes iekÅ”Äjo stÄvokli.
- Izveidot Änu DOM, izmantojot
this.attachShadow({ mode: 'open' })
vaithis.attachShadow({ mode: 'closed' })
.mode
nosaka, vai Änu DOM ir pieejams no JavaScript Ärpus komponentes (open
) vai nÄ (closed
). Parasti ieteicams izmantotopen
vieglÄkai atkļūdoÅ”anai. - PiesaistÄ«t notikumu apstrÄdes metodes komponentes instancei (izmantojot
this.methodName = this.methodName.bind(this)
), lai nodroÅ”inÄtu, kathis
apstrÄdÄtÄjÄ atsaucas uz komponentes instanci.
SvarÄ«gi apsvÄrumi konstruktoram:
- Jums nevajadzÄtu veikt nekÄdas DOM manipulÄcijas konstruktorÄ. Elements vÄl nav pilnÄ«bÄ pievienots DOM, un mÄÄ£inÄjums to modificÄt var izraisÄ«t neparedzÄtu uzvedÄ«bu. Izmantojiet
connectedCallback
DOM manipulÄcijÄm. - Izvairieties no atribÅ«tu izmantoÅ”anas konstruktorÄ. AtribÅ«ti vÄl var nebÅ«t pieejami. TÄ vietÄ izmantojiet
connectedCallback
vaiattributeChangedCallback
. - Vispirms izsauciet
super()
. Tas ir obligÄti, ja jÅ«s paplaÅ”inÄt citu klasi (parastiHTMLElement
).
PiemÄrs:
class MyCustomElement extends HTMLElement {
constructor() {
super();
// Create a shadow root
this.shadow = this.attachShadow({mode: 'open'});
this.message = "Hello, world!";
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
alert(this.message);
}
}
2. connectedCallback()
connectedCallback
tiek izsaukta, kad pielÄgotais elements tiek pievienots dokumenta DOM. Å Ä« ir galvenÄ vieta, kur:
- IelÄdÄt datus no API.
- Pievienot notikumu klausÄ«tÄjus komponentei vai tÄs Änu DOM.
- RenderÄt komponentes sÄkotnÄjo saturu Änu DOM.
- NovÄrot atribÅ«tu izmaiÅas, ja tÅ«lÄ«tÄja novÄroÅ”ana konstruktorÄ nav iespÄjama.
PiemÄrs:
class MyCustomElement extends HTMLElement {
// ... constructor ...
connectedCallback() {
// Create a button element
const button = document.createElement('button');
button.textContent = 'Click me!';
button.addEventListener('click', this.handleClick);
this.shadow.appendChild(button);
// Fetch data (example)
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
this.data = data;
this.render(); // Call a render method to update the UI
});
}
render() {
// Update the Shadow DOM based on the data
const dataElement = document.createElement('p');
dataElement.textContent = JSON.stringify(this.data);
this.shadow.appendChild(dataElement);
}
handleClick() {
alert("Button clicked!");
}
}
3. disconnectedCallback()
disconnectedCallback
tiek izsaukta, kad pielÄgotais elements tiek atvienots no dokumenta DOM. Tas ir bÅ«tiski, lai:
- NoÅemtu notikumu klausÄ«tÄjus, lai novÄrstu atmiÅas noplÅ«des.
- Atceltu jebkÄdus taimerus vai intervÄlus.
- Atbrīvotu jebkurus resursus, kurus komponente izmanto.
PiemÄrs:
class MyCustomElement extends HTMLElement {
// ... constructor, connectedCallback ...
disconnectedCallback() {
// Remove the event listener
this.shadow.querySelector('button').removeEventListener('click', this.handleClick);
// Cancel any timers (example)
if (this.timer) {
clearInterval(this.timer);
}
console.log('Component disconnected from the DOM.');
}
}
4. attributeChangedCallback(name, oldValue, newValue)
attributeChangedCallback
tiek izsaukta katru reizi, kad tiek mainÄ«ts pielÄgotÄ elementa atribÅ«ts, bet tikai tiem atribÅ«tiem, kas norÄdÄ«ti observedAttributes
statiskajÄ getterÄ«. Å Ä« metode ir bÅ«tiska, lai:
- ReaÄ£Ätu uz atribÅ«tu vÄrtÄ«bu izmaiÅÄm un atjauninÄtu komponentes uzvedÄ«bu vai izskatu.
- ValidÄtu atribÅ«tu vÄrtÄ«bas.
Galvenie aspekti:
- Jums ir jÄdefinÄ statiskais getteris ar nosaukumu
observedAttributes
, kas atgriež novÄrojamo atribÅ«tu nosaukumu masÄ«vu. attributeChangedCallback
tiks izsaukta tikai tiem atribÅ«tiem, kas norÄdÄ«tiobservedAttributes
.- Metode saÅem trÄ«s argumentus: mainÄ«tÄ atribÅ«ta
name
(nosaukums),oldValue
(vecÄ vÄrtÄ«ba) unnewValue
(jaunÄ vÄrtÄ«ba). oldValue
būsnull
, ja atribūts tika tikko pievienots.
PiemÄrs:
class MyCustomElement extends HTMLElement {
// ... constructor, connectedCallback, disconnectedCallback ...
static get observedAttributes() {
return ['message', 'data-count']; // Observe the 'message' and 'data-count' attributes
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'message') {
this.message = newValue; // Update the internal state
this.renderMessage(); // Re-render the message
} else if (name === 'data-count') {
const count = parseInt(newValue, 10);
if (!isNaN(count)) {
this.count = count; // Update the internal count
this.renderCount(); // Re-render the count
} else {
console.error('Invalid data-count attribute value:', newValue);
}
}
}
renderMessage() {
// Update the message display in the Shadow DOM
let messageElement = this.shadow.querySelector('.message');
if (!messageElement) {
messageElement = document.createElement('p');
messageElement.classList.add('message');
this.shadow.appendChild(messageElement);
}
messageElement.textContent = this.message;
}
renderCount(){
let countElement = this.shadow.querySelector('.count');
if(!countElement){
countElement = document.createElement('p');
countElement.classList.add('count');
this.shadow.appendChild(countElement);
}
countElement.textContent = `Count: ${this.count}`;
}
}
Efektīva attributeChangedCallback izmantoŔana:
- ValidÄjiet ievadi: Izmantojiet atzvanu, lai validÄtu jauno vÄrtÄ«bu un nodroÅ”inÄtu datu integritÄti.
- Atlikt atjauninÄjumus (Debounce Updates): SkaitļoÅ”anas ziÅÄ dÄrgiem atjauninÄjumiem apsveriet iespÄju atlikt atribÅ«tu izmaiÅu apstrÄdÄtÄja izsaukÅ”anu, lai izvairÄ«tos no pÄrmÄrÄ«gas pÄrrenderÄÅ”anas.
- Apsveriet alternatÄ«vas: Sarežģītiem datiem apsveriet iespÄju izmantot rekvizÄ«tus (properties), nevis atribÅ«tus, un apstrÄdÄjiet izmaiÅas tieÅ”i rekvizÄ«ta setterÄ«.
5. adoptedCallback()
adoptedCallback
tiek izsaukta, kad pielÄgotais elements tiek pÄrvietots uz jaunu dokumentu (piemÄram, no viena iframe uz citu). Å Ä« ir retÄk izmantota dzÄ«ves cikla metode, bet ir svarÄ«gi to zinÄt, strÄdÄjot ar sarežģītÄkiem scenÄrijiem, kas ietver dokumentu kontekstus.
PiemÄrs:
class MyCustomElement extends HTMLElement {
// ... constructor, connectedCallback, disconnectedCallback, attributeChangedCallback ...
adoptedCallback() {
console.log('Component adopted into a new document.');
// Perform any necessary adjustments when the component is moved to a new document
// This might involve updating references to external resources or re-establishing connections.
}
}
PielÄgota elementa definÄÅ”ana
Kad esat definÄjis savu pielÄgotÄ elementa klasi, jums tÄ jÄreÄ£istrÄ pÄrlÅ«kprogrammÄ, izmantojot customElements.define()
:
customElements.define('my-custom-element', MyCustomElement);
Pirmais arguments ir jÅ«su pielÄgotÄ elementa taga nosaukums (piem., 'my-custom-element'
). Taga nosaukumam obligÄti jÄsatur domuzÄ«me (-
), lai izvairītos no konfliktiem ar standarta HTML elementiem.
Otrais arguments ir klase, kas definÄ jÅ«su pielÄgotÄ elementa uzvedÄ«bu (piem., MyCustomElement
).
PÄc pielÄgotÄ elementa definÄÅ”anas jÅ«s varat to izmantot savÄ HTML kÄ jebkuru citu HTML elementu:
<my-custom-element message="Hello from attribute!" data-count="10"></my-custom-element>
LabÄkÄs prakses tÄ«mekļa komponentu dzÄ«ves cikla pÄrvaldÄ«bÄ
- Uzturiet konstruktoru vienkÄrÅ”u: Izvairieties no DOM manipulÄcijÄm vai sarežģītiem aprÄÄ·iniem konstruktorÄ. Å iem uzdevumiem izmantojiet
connectedCallback
. - Atbrīvojiet resursus
disconnectedCallback
: VienmÄr noÅemiet notikumu klausÄ«tÄjus, atceliet taimerus un atbrÄ«vojiet resursusdisconnectedCallback
, lai novÄrstu atmiÅas noplÅ«des. - Gudri izmantojiet
observedAttributes
: NovÄrojiet tikai tos atribÅ«tus, uz kuriem jums patieÅ”Äm ir jÄreaÄ£Ä. NevajadzÄ«gu atribÅ«tu novÄroÅ”ana var ietekmÄt veiktspÄju. - Apsveriet renderÄÅ”anas bibliotÄkas izmantoÅ”anu: Sarežģītiem lietotÄja saskarnes atjauninÄjumiem apsveriet iespÄju izmantot renderÄÅ”anas bibliotÄku, piemÄram, LitElement vai uhtml, lai vienkÄrÅ”otu procesu un uzlabotu veiktspÄju.
- RÅ«pÄ«gi pÄrbaudiet savas komponentes: Rakstiet vienÄ«btestus, lai nodroÅ”inÄtu, ka jÅ«su komponentes darbojas pareizi visÄ to dzÄ«ves ciklÄ.
PiemÄrs: VienkÄrÅ”a skaitÄ«tÄja komponente
Izveidosim vienkÄrÅ”u skaitÄ«tÄja komponenti, kas demonstrÄ tÄ«mekļa komponentes dzÄ«ves cikla izmantoÅ”anu:
class CounterComponent extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'open' });
this.count = 0;
this.increment = this.increment.bind(this);
}
connectedCallback() {
this.render();
this.shadow.querySelector('button').addEventListener('click', this.increment);
}
disconnectedCallback() {
this.shadow.querySelector('button').removeEventListener('click', this.increment);
}
increment() {
this.count++;
this.render();
}
render() {
this.shadow.innerHTML = `
<p>Count: ${this.count}</p>
<button>Increment</button>
`;
}
}
customElements.define('counter-component', CounterComponent);
Å Ä« komponente uztur iekÅ”Äjo count
mainÄ«go un atjaunina displeju, kad tiek noklikŔķinÄts uz pogas. connectedCallback
pievieno notikumu klausÄ«tÄju, un disconnectedCallback
to noÅem.
PadziļinÄtas tÄ«mekļa komponentu tehnikas
1. RekvizÄ«tu (Properties) izmantoÅ”ana atribÅ«tu vietÄ
Lai gan atribÅ«ti ir noderÄ«gi vienkÄrÅ”iem datiem, rekvizÄ«ti (properties) piedÄvÄ lielÄku elastÄ«bu un tipu droŔību. JÅ«s varat definÄt rekvizÄ«tus savam pielÄgotajam elementam un izmantot getterus un setterus, lai kontrolÄtu, kÄ tiem piekļūst un tos modificÄ.
class MyCustomElement extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'open' });
this._data = null; // Use a private property to store the data
}
get data() {
return this._data;
}
set data(value) {
this._data = value;
this.renderData(); // Re-render the component when the data changes
}
connectedCallback() {
// Initial rendering
this.renderData();
}
renderData() {
// Update the Shadow DOM based on the data
this.shadow.innerHTML = `<p>Data: ${JSON.stringify(this._data)}</p>`;
}
}
customElements.define('my-data-element', MyCustomElement);
PÄc tam jÅ«s varat iestatÄ«t data
rekvizītu tieŔi JavaScript:
const element = document.querySelector('my-data-element');
element.data = { name: 'John Doe', age: 30 };
2. Notikumu (Events) izmantoÅ”ana saziÅai
PielÄgoti notikumi (custom events) ir spÄcÄ«gs veids, kÄ tÄ«mekļa komponentes var sazinÄties savÄ starpÄ un ar Ärpasauli. JÅ«s varat nosÅ«tÄ«t pielÄgotus notikumus no savas komponentes un klausÄ«ties tos citÄs lietotnes daļÄs.
class MyCustomElement extends HTMLElement {
// ... constructor, connectedCallback ...
dispatchCustomEvent() {
const event = new CustomEvent('my-custom-event', {
detail: { message: 'Hello from the component!' },
bubbles: true, // Allow the event to bubble up the DOM tree
composed: true // Allow the event to cross the shadow DOM boundary
});
this.dispatchEvent(event);
}
}
customElements.define('my-event-element', MyCustomElement);
// Listen for the custom event in the parent document
document.addEventListener('my-custom-event', (event) => {
console.log('Custom event received:', event.detail.message);
});
3. Änu DOM (Shadow DOM) stilizÄÅ”ana
Änu DOM nodroÅ”ina stila iekapsulÄÅ”anu, novÄrÅ”ot stilu noplÅ«di komponentÄ vai no tÄs. JÅ«s varat stilizÄt savas tÄ«mekļa komponentes, izmantojot CSS Änu DOM iekÅ”ienÄ.
Iekļautie stili:
class MyCustomElement extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'open' });
this.shadow.innerHTML = `
<style>
p {
color: blue;
}
</style>
<p>This is a styled paragraph.</p>
`;
}
}
ÄrÄjÄs stila lapas:
JÅ«s varat arÄ« ielÄdÄt ÄrÄjÄs stila lapas Änu DOM:
class MyCustomElement extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'open' });
const linkElem = document.createElement('link');
linkElem.setAttribute('rel', 'stylesheet');
linkElem.setAttribute('href', 'my-component.css');
this.shadow.appendChild(linkElem);
this.shadow.innerHTML += '<p>This is a styled paragraph.</p>';
}
}
NoslÄgums
TÄ«mekļa komponentu dzÄ«ves cikla apguve ir bÅ«tiska, lai veidotu noturÄ«gas un atkÄrtoti lietojamas komponentes modernÄm tÄ«mekļa lietotnÄm. Izprotot dažÄdÄs dzÄ«ves cikla metodes un izmantojot labÄkÄs prakses, jÅ«s varat izveidot komponentes, kuras ir viegli uzturÄt, veiktspÄjÄ«gas un nevainojami integrÄjas ar citÄm jÅ«su lietotnes daļÄm. Å is ceļvedis sniedza visaptveroÅ”u pÄrskatu par tÄ«mekļa komponentu dzÄ«ves ciklu, ietverot detalizÄtus paskaidrojumus, praktiskus piemÄrus un padziļinÄtas tehnikas. Izmantojiet tÄ«mekļa komponentu spÄku un veidojiet modulÄras, uzturÄjamas un mÄrogojamas tÄ«mekļa lietotnes.
Papildu resursi:
- MDN Web Docs: PlaÅ”a dokumentÄcija par tÄ«mekļa komponentÄm un pielÄgotajiem elementiem.
- WebComponents.org: Kopienas virzÄ«ts resurss tÄ«mekļa komponentu izstrÄdÄtÄjiem.
- LitElement: VienkÄrÅ”a bÄzes klase ÄtrdarbÄ«gu, vieglu tÄ«mekļa komponentu izveidei.