# lifecycle methods

[browser](/web/browser.md) ⟩ [web components](/web/component.md) ⟩ [implement](/web/component/implement.md) ⟩ [custom elements](/web/component/custom-element.md) ⟩ lifecycle methods

{% tabs %}
{% tab title="⭐️ 重點" %}
{% hint style="success" %}

* <mark style="color:yellow;">**constructor**</mark>()\
  an instance of custom element is **created** or **upgraded**.
* <mark style="color:yellow;">**connectedCallback**</mark>()\
  custom element is **appended** into/**moved** in a document.
* <mark style="color:orange;">**disconnectedCallback**</mark>()\
  custom element is **removed** from the document.
* <mark style="color:yellow;">**attributeChangedCallback**</mark>(<mark style="color:blue;">attrName</mark>, <mark style="color:blue;">oldVal</mark>, <mark style="color:blue;">newVal</mark>)\
  one of the custom element’s **attributes** is **added**/**removed**/**changed**. \
  observed attributes are specified with <mark style="color:blue;">`static get observedAttributes()`</mark>.
* <mark style="color:orange;">**adoptedCallback**</mark>()\
  custom element is **moved** to a **new document**.
  {% endhint %}
  {% endtab %}

{% tab title="📘 手冊" %}

* MDN ⟩ [Using the lifecycle callbacks](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#using_the_lifecycle_callbacks)
* Google ⟩ [Custom element reactions](https://developers.google.com/web/fundamentals/web-components/customelements#reactions) - a.k.a lifecycle callbacks
  {% endtab %}

{% tab title="📗 參考" %}

* [ ] JavaScript: The Definitive Guide (15.6 Web Components)
  {% endtab %}

{% tab title="💈範例" %}
:floppy\_disk: [web component life cycle](https://replit.com/@pegasusroe/web-component-life-cycle#script.js)

{% embed url="<https://codepen.io/lochiwei/pen/JjJXVrW>" %}

📁 HTML

```html
<div id="parent">
    <!-- web component -->
    <my-component text="my personal text"></my-component>
</div>

<button id="button" onclick="removeElement()">Remove Element</button>
```

📁 JS

```javascript
// ⭐️ 1. custom web component
class MyComponent extends HTMLElement {

    constructor(){ 
        
        // debug info
        console.log(`🐣 contructed ...`);

        // tell HTMLElement to initialize itself
        super();

        // variables
        const text = this.getAttribute('text') || 'Loren Ipsum';
        const size = randomInt(12, 50);     // random font size

        // create element
        const elem = document.createElement('template');
        elem.innerHTML = MyComponent.template(text, size);

        // add to UI
        this.appendChild(document.importNode(elem.content, true));
    }

    // HTML tempalte
    static template(text, size) { 
        return `
            <div style="font-size:${size}px">
                ${text} (font-size: ${size})
            </div>
        `;
    }

    /* -------- life-cycle triggers -------- */

    connectedCallback() { console.log(`🔌 connected ...`); } 
    disconnectedCallback() { console.log(`❌ disconnected ...`); }

    attributeChangedCallback(attrName, oldVal, newVal) { 
        console.log(`✏️ attribute "${attrName}" changed: ${oldVal} ➝ ${newVal}`); 
    }

    /*
        To get the attributeChangedCallback() method to work correctly, 
        we must add the static method observedAttributes() and 
        return the properties that we want to observe.
    */
    static get observedAttributes() { 
        return ['text']; 
    }

    /* --------- set/get `text` ---------- */

    set text(val) { this.setAttribute(`text`, val ?? ``); }
    get text() { return this.getAttribute('text'); }
} 

// ⭐️ 2. custom tag <my-component>
// ⭐️⭐️ custom element names must contain a "hyphen".
customElements.define('my-component', MyComponent);


/* -------- button -------- */

function removeElement() {

    const div = $('#parent');
    const element = $('my-component');
    const button = $('#button');

    div.removeChild(element);
    button.disabled = true;
}

/* -------- helpers -------- */

// $ ⭐️
function $(selector, parent = document){
  return parent.querySelector(selector);
}

// random integer between a and b
function randomInt(a, b){
    return Math.floor((Math.random() * (b - a + 1)) + a)
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lochiwei.gitbook.io/web/component/custom-element/lifecycle.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
