Ðи можемо ÑÑвоÑÑваÑи влаÑÐ½Ñ HTML-елеменÑи, опиÑÐ°Ð½Ñ Ð½Ð°Ñим клаÑом, з влаÑними меÑодами Ñа влаÑÑивоÑÑÑми, подÑÑми ÑоÑо.
ÐÑÑÐ»Ñ Ð²Ð¸Ð·Ð½Ð°ÑÐµÐ½Ð½Ñ ÐºÐ°ÑÑомного елеменÑа ми можемо викоÑиÑÑовÑваÑи його наÑÑÐ²Ð½Ñ Ð· вбÑдованими HTML-елеменÑами.
Це ÑÑдово, оÑкÑлÑки Ñловник HTML багаÑий, але не неÑкÑнÑенний. У нÑÐ¾Ð¼Ñ Ð½ÐµÐ¼Ð°Ñ ÑегÑв <easy-tabs>, <sliding-carousel>, <beautiful-upload>⦠ÐÑоÑÑо пÑидÑмайÑе бÑдÑ-Ñкий ÑнÑий Ñег, Ñкий нам може знадобиÑиÑÑ.
Ðи можемо визнаÑиÑи ÑÑ Ð·Ð° Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¾Ñ ÑпеÑÑалÑного клаÑÑ, а поÑÑм викоÑиÑÑовÑваÑи Ñак, нÑби вони завжди бÑли ÑаÑÑÐ¸Ð½Ð¾Ñ HTML.
ÐÑнÑÑ Ð´Ð²Ð° Ñипи каÑÑÐ¾Ð¼Ð½Ð¸Ñ ÐµÐ»ÐµÐ¼ÐµÐ½ÑÑв:
- ÐвÑÐ¾Ð½Ð¾Ð¼Ð½Ñ ÐºÐ°ÑÑÐ¾Ð¼Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи â âабÑолÑÑно новÑâ елеменÑи, Ñо ÑозÑиÑÑÑÑÑ Ð°Ð±ÑÑÑакÑний клаÑ
HTMLElement. - ÐаÑÑомÑÐ·Ð¾Ð²Ð°Ð½Ñ Ð²Ð±ÑÐ´Ð¾Ð²Ð°Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи â ÑозÑиÑÐµÐ½Ð½Ñ Ð²Ð±ÑдованиÑ
елеменÑÑв, напÑиклад, каÑÑомÑÐ·Ð¾Ð²Ð°Ð½Ð¾Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸, на оÑновÑ
HTMLButtonElementÑоÑо.
СпоÑаÑÐºÑ Ð¼Ð¸ ÑозглÑнемо авÑÐ¾Ð½Ð¾Ð¼Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи, а поÑÑм пеÑейдемо до каÑÑомÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ð±ÑÐ´Ð¾Ð²Ð°Ð½Ð¸Ñ .
Щоб ÑÑвоÑиÑи каÑÑомний елеменÑ, нам поÑÑÑбно вказаÑи бÑаÑзеÑÑ ÐºÑлÑка деÑалей пÑо нÑого: Ñк його показÑваÑи, Ñо ÑобиÑи, коли ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð´Ð¾Ð´Ð°ÑÑÑÑÑ Ð°Ð±Ð¾ видалÑÑÑÑÑÑ Ð·Ñ ÑÑоÑÑнки ÑоÑо.
Це ÑобиÑÑÑÑ ÑлÑÑ Ð¾Ð¼ ÑÑвоÑÐµÐ½Ð½Ñ ÐºÐ»Ð°ÑÑ Ð·Ñ ÑпеÑÑалÑними меÑодами. Це легко, оÑкÑлÑки меÑодÑв небагаÑо, Ñ Ð²ÑÑ Ð²Ð¾Ð½Ð¸ необовâÑзковÑ.
ÐÑÑ ÑеÑнеÑка з повним ÑпиÑком:
class MyElement extends HTMLElement {
constructor() {
super();
// ÐµÐ»ÐµÐ¼ÐµÐ½Ñ ÑÑвоÑено
}
connectedCallback() {
// бÑаÑÐ·ÐµÑ Ð²Ð¸ÐºÐ»Ð¸ÐºÐ°Ñ Ñей меÑод пÑи Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½ÑÑ Ð² докÑменÑ
// (може викликаÑиÑÑ Ð±Ð°Ð³Ð°Ñо ÑазÑв, ÑкÑо ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð½ÐµÐ¾Ð´Ð½Ð¾Ñазово додаÑÑÑÑÑ/видалÑÑÑÑÑÑ)
}
disconnectedCallback() {
// бÑаÑÐ·ÐµÑ Ð²Ð¸ÐºÐ»Ð¸ÐºÐ°Ñ Ñей меÑод пÑи Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½ÑÑ Ð· докÑменÑÑ
// (може викликаÑиÑÑ Ð±Ð°Ð³Ð°Ñо ÑазÑв, ÑкÑо ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð½ÐµÐ¾Ð´Ð½Ð¾Ñазово додаÑÑÑÑÑ/видалÑÑÑÑÑÑ)
}
static get observedAttributes() {
return [/* маÑив Ñмен аÑÑибÑÑÑв Ð´Ð»Ñ Ð¼Ð¾Ð½ÑÑоÑÐ¸Ð½Ð³Ñ Ð·Ð¼Ñн */];
}
attributeChangedCallback(name, oldValue, newValue) {
// викликаÑÑÑÑÑ Ð¿Ñи змÑÐ½Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ з пеÑеÑаÑ
ованиÑ
виÑе аÑÑибÑÑÑв
}
adoptedCallback() {
// викликаÑÑÑÑÑ, коли ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð¿ÐµÑемÑÑÑÑÑÑÑÑ Ð² новий докÑменÑ
// (вÑдбÑваÑÑÑÑÑ Ð² document.adoptNode, дÑже ÑÑдко викоÑиÑÑовÑÑÑÑÑÑ)
}
// ÑÑÑ Ð¼Ð¾Ð¶ÑÑÑ Ð±ÑÑи ÑнÑÑ Ð¼ÐµÑоди Ñа влаÑÑивоÑÑÑ ÐµÐ»ÐµÐ¼ÐµÐ½Ñа
}
ÐÑÑÐ»Ñ ÑÑого нам поÑÑÑбно заÑеÑÑÑÑÑваÑи елеменÑ:
// повÑдомлÑÑмо бÑаÑзеÑÑ, Ñо <my-element> обÑлÑговÑÑÑÑÑÑ Ð½Ð°Ñим новим клаÑом
customElements.define("my-element", MyElement);
Ð¢ÐµÐ¿ÐµÑ Ð´Ð»Ñ Ð±ÑдÑ-Ñкого HTML-елеменÑа з Ñегом <my-element> ÑÑвоÑÑÑÑÑÑÑ ÐµÐºÐ·ÐµÐ¼Ð¿Ð»ÑÑ MyElement Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÐ°ÑÑÑÑÑ Ð²Ð¸ÑÐµÐ·Ð³Ð°Ð´Ð°Ð½Ñ Ð¼ÐµÑоди. Ðи Ñакож можемо викликаÑи document.createElement('my-element') в JavaScript.
-ÐмâÑ ÐºÐ°ÑÑомного елеменÑа повинно мÑÑÑиÑи деÑÑÑ -, напÑиклад, my-element Ñ super-button Ñ Ð´Ð¾Ð¿ÑÑÑимими Ñменами, а myelement â нÑ.
Це ÑобиÑÑÑÑ Ð´Ð»Ñ Ñого, Ñоб ÑникнÑÑи конÑлÑкÑÑв Ñмен мÑж вбÑдованими Ñа каÑÑомними HTML-елеменÑами.
ÐÑиклад: âtime-formattedâ
ÐапÑиклад, в HTML вже ÑÑнÑÑ ÐµÐ»ÐµÐ¼ÐµÐ½Ñ <time> Ð´Ð»Ñ Ð¿Ð¾Ð·Ð½Ð°ÑÐµÐ½Ð½Ñ Ð´Ð°Ñи/ÑаÑÑ. Ðле вÑн Ñам по ÑÐ¾Ð±Ñ Ð½Ðµ виконÑÑ Ð½ÑÑкого ÑоÑмаÑÑваннÑ.
ÐавайÑе ÑÑвоÑимо ÐµÐ»ÐµÐ¼ÐµÐ½Ñ <time-formatted>, Ñкий вÑдобÑажаÑиме ÑÐ°Ñ Ñ Ð³Ð°ÑномÑ, зÑозÑмÑÐ»Ð¾Ð¼Ñ ÑоÑмаÑÑ:
<script>
class TimeFormatted extends HTMLElement { // (1)
connectedCallback() {
let date = new Date(this.getAttribute('datetime') || Date.now());
this.innerHTML = new Intl.DateTimeFormat("default", {
year: this.getAttribute('year') || undefined,
month: this.getAttribute('month') || undefined,
day: this.getAttribute('day') || undefined,
hour: this.getAttribute('hour') || undefined,
minute: this.getAttribute('minute') || undefined,
second: this.getAttribute('second') || undefined,
timeZoneName: this.getAttribute('time-zone-name') || undefined,
}).format(date);
}
}
customElements.define("time-formatted", TimeFormatted); // (2)
</script>
<!-- (3) -->
<time-formatted datetime="2019-12-01"
year="numeric" month="long" day="numeric"
hour="numeric" minute="numeric" second="numeric"
time-zone-name="short"
></time-formatted>
- ÐÐ»Ð°Ñ Ð¼Ð°Ñ Ð»Ð¸Ñе один меÑод
connectedCallback()â бÑаÑÐ·ÐµÑ Ð²Ð¸ÐºÐ»Ð¸ÐºÐ°Ñ Ð¹Ð¾Ð³Ð¾, коли на ÑÑоÑÑÐ½ÐºÑ Ð´Ð¾Ð´Ð°ÑÑÑÑÑ ÐµÐ»ÐµÐ¼ÐµÐ½Ñ<time-formatted>(або коли паÑÑÐµÑ HTML виÑвлÑÑ Ð¹Ð¾Ð³Ð¾), Ñ Ð²Ð¸ÐºÐ¾ÑиÑÑовÑÑ Ð²Ð±Ñдований ÑоÑмаÑÐµÑ Ð´Ð°Ð½Ð¸Ñ Intl.DateTimeFormat, Ñкий добÑе пÑдÑÑимÑÑÑÑÑÑ Ð²ÑÑма бÑаÑзеÑами, Ñоб показаÑи вÑдÑоÑмаÑований ÑаÑ. - Ðам поÑÑÑбно заÑеÑÑÑÑÑваÑи Ð½Ð°Ñ Ð½Ð¾Ð²Ð¸Ð¹ ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð·Ð° допомогоÑ
customElements.define(tag, class). - Ð ÑÐ¾Ð´Ñ Ð¼Ð¸ зможемо викоÑиÑÑовÑваÑи його бÑдÑ-де.
ЯкÑо бÑаÑÐ·ÐµÑ Ð·ÑÑÑÑÑÑÐ°Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи <time-formatted> пеÑед customElements.define, Ñе не Ñ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ¾Ñ. Ðле ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ñе невÑдомий, Ñк Ñ Ð±ÑдÑ-Ñкий неÑÑандаÑÑний Ñег.
Ð¢Ð°ÐºÑ âневизнаÑенÑâ елеменÑи можна ÑÑилÑзÑваÑи за Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¾Ñ CSS-ÑелекÑоÑа :not(:defined).
Ðоли викликаÑÑÑÑÑ customElement.define, вони âоновлÑÑÑÑÑÑâ: Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ ÑÑвоÑÑÑÑÑÑÑ Ð½Ð¾Ð²Ð¸Ð¹ екземплÑÑ TimeFormatted
Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÐ°ÑÑÑÑÑ connectedCallback. ÐÑÑÐ»Ñ ÑÑого вони ÑÑаÑÑÑ :defined.
ÐÐ»Ñ Ð¾ÑÑÐ¸Ð¼Ð°Ð½Ð½Ñ ÑнÑоÑмаÑÑÑ Ð¿Ñо каÑÑÐ¾Ð¼Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи ÑÑнÑÑÑÑ ÑÐ°ÐºÑ Ð¼ÐµÑоди:
customElements.get(name)â повеÑÑÐ°Ñ ÐºÐ»Ð°Ñ ÐºÐ°ÑÑомного елеменÑа з заданим Ñменемname,customElements.whenDefined(name)â повеÑÑÐ°Ñ Ð¿ÑомÑÑ, Ñкий виконÑÑÑÑÑÑ (без знаÑеннÑ), коли каÑÑомний ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð· заданим ÑменемnameÑÑÐ°Ñ Ð²Ð¸Ð·Ð½Ð°Ñеним.
connectedCallback, а не в constructorУ Ð½Ð°Ð²ÐµÐ´ÐµÐ½Ð¾Ð¼Ñ Ð²Ð¸Ñе пÑÐ¸ÐºÐ»Ð°Ð´Ñ Ð²Ð¼ÑÑÑ ÐµÐ»ÐµÐ¼ÐµÐ½Ñа ÑендеÑиÑÑÑÑ (ÑÑвоÑÑÑÑÑÑÑ) в connectedCallback.
Ð§Ð¾Ð¼Ñ Ð½Ðµ в constructor?
ÐÑиÑина пÑоÑÑа: коли викликаÑÑÑÑÑ constructor, Ñе занадÑо Ñано. ÐÐ»ÐµÐ¼ÐµÐ½Ñ ÑÑвоÑено, але бÑаÑÐ·ÐµÑ Ñе не вÑÑиг обÑобиÑи/пÑиÑвоÑÑи аÑÑибÑÑи на ÑÑÐ¾Ð¼Ñ ÐµÑапÑ: виклик getAttribute повеÑне null. ÐÑже, ми не можемо ÑендеÑиÑи.
Ðо Ñого ж, ÑкÑо подÑмаÑи, Ñо Ñе кÑаÑе з ÑоÑки зоÑÑ Ð¿ÑодÑкÑивноÑÑÑ â вÑдклаÑÑи ÑобоÑÑ Ð´Ð¾ Ñого моменÑÑ, коли вона дÑйÑно бÑде поÑÑÑбна.
ФÑнкÑÑÑ connectedCallback ÑпÑаÑÑовÑÑ, коли ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð´Ð¾Ð´Ð°ÑÑÑÑÑ Ð´Ð¾ докÑменÑа. Ðе пÑоÑÑо додаÑÑÑÑÑ Ð´Ð¾ ÑнÑого елеменÑа Ñк доÑÑÑнÑй, а ÑакÑиÑно ÑÑÐ°Ñ ÑаÑÑÐ¸Ð½Ð¾Ñ ÑÑоÑÑнки. Таким Ñином, ми можемо ÑÑвоÑÑваÑи вÑдокÑемлений DOM, ÑÑвоÑÑваÑи елеменÑи Ñ Ð³Ð¾ÑÑваÑи ÑÑ
Ð´Ð»Ñ Ð¿Ð¾Ð´Ð°Ð»ÑÑого викоÑиÑÑаннÑ. Ðони бÑдÑÑÑ ÑакÑиÑно вÑдобÑÐ°Ð¶ÐµÐ½Ñ Ð»Ð¸Ñе ÑодÑ, коли поÑÑаплÑÑÑ Ð½Ð° ÑÑоÑÑнкÑ.
ÐÑдÑÑежÑÐ²Ð°Ð½Ð½Ñ Ð°ÑÑибÑÑÑв
У поÑоÑнÑй ÑеалÑзаÑÑÑ <time-formatted> пÑÑÐ»Ñ Ð²ÑдобÑÐ°Ð¶ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñа подалÑÑÑ Ð·Ð¼Ñни аÑÑибÑÑÑв не маÑÑÑ Ð¶Ð¾Ð´Ð½Ð¾Ð³Ð¾ еÑекÑÑ. Це дивно Ð´Ð»Ñ HTML-елеменÑа. ÐазвиÑай, коли ми змÑнÑÑмо аÑÑибÑÑ, напÑиклад, a.href, ми оÑÑкÑÑмо, Ñо змÑни бÑде видно одÑазÑ. ÐавайÑе Ñе випÑавимо.
Ðи можемо вÑдÑÑежÑваÑи аÑÑибÑÑи, пеÑедавÑи ÑÑ
ÑпиÑок Ñ ÑÑаÑиÑний геÑÑÐµÑ observedAttributes(). ÐÐ»Ñ ÑакиÑ
аÑÑибÑÑÑв викликаÑÑÑÑÑ attributeChangedCallback пÑи ÑÑ
змÑнÑ. ÐÑн не ÑпÑаÑÑовÑÑ Ð´Ð»Ñ ÑнÑиÑ
, непеÑелÑÑениÑ
аÑÑибÑÑÑв (з мÑÑкÑÐ²Ð°Ð½Ñ Ð¿ÑодÑкÑивноÑÑÑ).
ÐÑÑ Ð½Ð¾Ð²Ð¸Ð¹ <time-formatted>, Ñкий авÑомаÑиÑно оновлÑÑÑÑÑÑ Ð¿Ñи змÑÐ½Ñ Ð°ÑÑибÑÑÑв:
<script>
class TimeFormatted extends HTMLElement {
render() { // (1)
let date = new Date(this.getAttribute('datetime') || Date.now());
this.innerHTML = new Intl.DateTimeFormat("default", {
year: this.getAttribute('year') || undefined,
month: this.getAttribute('month') || undefined,
day: this.getAttribute('day') || undefined,
hour: this.getAttribute('hour') || undefined,
minute: this.getAttribute('minute') || undefined,
second: this.getAttribute('second') || undefined,
timeZoneName: this.getAttribute('time-zone-name') || undefined,
}).format(date);
}
connectedCallback() { // (2)
if (!this.rendered) {
this.render();
this.rendered = true;
}
}
static get observedAttributes() { // (3)
return ['datetime', 'year', 'month', 'day', 'hour', 'minute', 'second', 'time-zone-name'];
}
attributeChangedCallback(name, oldValue, newValue) { // (4)
this.render();
}
}
customElements.define("time-formatted", TimeFormatted);
</script>
<time-formatted id="elem" hour="numeric" minute="numeric" second="numeric"></time-formatted>
<script>
setInterval(() => elem.setAttribute('datetime', new Date()), 1000); // (5)
</script>
- ÐогÑÐºÑ Ð²ÑдобÑÐ°Ð¶ÐµÐ½Ð½Ñ Ð¿ÐµÑенеÑено Ñ Ð´Ð¾Ð¿Ð¾Ð¼Ñжний меÑод
render(). - Ðи викликаÑмо його пеÑÑий Ñаз, коли ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð²ÑÑавлÑÑÑÑÑÑ Ð½Ð° ÑÑоÑÑнкÑ.
- ÐÑи змÑÐ½Ñ Ð°ÑÑибÑÑа, пеÑеÑаÑ
ованого в
observedAttributes(), ÑпÑаÑÑовÑÑattributeChangedCallback. - â¦ÑкÑй повÑоÑно вÑдÑендеÑиÑÑ ÐµÐ»ÐµÐ¼ÐµÐ½Ñ.
- ÐÑеÑÑоÑ, ми можемо легко зÑобиÑи ÑаймеÑ.
ÐоÑÑдок вÑдобÑаженнÑ
Ðоли HTML-паÑÑÐµÑ Ð±ÑдÑÑ DOM, елеменÑи обÑоблÑÑÑÑÑÑ Ð¾Ð´Ð¸Ð½ за одним, ÑпоÑаÑÐºÑ Ð±Ð°ÑÑки, поÑÑм дÑÑи. ÐапÑиклад, ÑкÑо ми маÑмо <outer><inner></inner></outer>, Ñо ÑпоÑаÑÐºÑ ÑÑвоÑÑÑÑÑÑÑ Ñ Ð¿ÑдклÑÑаÑÑÑÑÑ Ð´Ð¾ DOM ÐµÐ»ÐµÐ¼ÐµÐ½Ñ <outer>, а поÑÑм <inner>.
Це пÑизводиÑÑ Ð´Ð¾ Ð²Ð°Ð¶Ð»Ð¸Ð²Ð¸Ñ Ð½Ð°ÑлÑдкÑв Ð´Ð»Ñ ÐºÐ°ÑÑÐ¾Ð¼Ð½Ð¸Ñ ÐµÐ»ÐµÐ¼ÐµÐ½ÑÑв.
ÐапÑиклад, ÑкÑо каÑÑомний ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð½Ð°Ð¼Ð°Ð³Ð°ÑÑÑÑÑ Ð¾ÑÑимаÑи доÑÑÑп до innerHTML в connectedCallback, Ñо вÑн нÑÑого не оÑÑимаÑ:
<script>
customElements.define('user-info', class extends HTMLElement {
connectedCallback() {
alert(this.innerHTML); // empty (*)
}
});
</script>
<user-info>John</user-info>
ЯкÑо ви запÑÑÑиÑе Ñей код, Ñо alert бÑде поÑожнÑм.
Це Ñаме ÑомÑ, Ñо на ÑÑÐ¾Ð¼Ñ ÐµÑÐ°Ð¿Ñ Ñе Ð½ÐµÐ¼Ð°Ñ Ð´Ð¾ÑÑÑнÑÑ
елеменÑÑв, ÑобÑо DOM Ñ Ð½ÐµÐ·Ð°Ð²ÐµÑÑеним. ÐаÑÑÐµÑ HTML пÑдклÑÑив каÑÑомний ÐµÐ»ÐµÐ¼ÐµÐ½Ñ <user-info>, Ñ Ð·Ð±Ð¸ÑаÑÑÑÑÑ Ð¿ÐµÑейÑи до його доÑÑÑнÑÑ
елеменÑÑв, але пÑоÑÑо Ñе не зÑобив ÑÑого.
ЯкÑо ми Ñ Ð¾Ñемо пеÑедаÑи ÑнÑоÑмаÑÑÑ ÐºÐ°ÑÑÐ¾Ð¼Ð½Ð¾Ð¼Ñ ÐµÐ»ÐµÐ¼ÐµÐ½ÑÑ, ми можемо викоÑиÑÑовÑваÑи аÑÑибÑÑи. Ðони доÑÑÑÐ¿Ð½Ñ Ð²ÑдÑазÑ.
Ðбо, ÑкÑо нам дÑйÑно поÑÑÑÐ±Ð½Ñ Ð´Ð¾ÑÑÑÐ½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи, ми можемо вÑдклаÑÑи доÑÑÑп до ниÑ
за Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¾Ñ setTimeout з нÑлÑÐ¾Ð²Ð¾Ñ Ð·Ð°ÑÑимкоÑ.
ÐапÑиклад, Ñаким Ñином:
<script>
customElements.define('user-info', class extends HTMLElement {
connectedCallback() {
setTimeout(() => alert(this.innerHTML)); // John (*)
}
});
</script>
<user-info>John</user-info>
Ð¢ÐµÐ¿ÐµÑ alert Ñ ÑÑÐ´ÐºÑ (*) показÑÑ âJohnâ, оÑкÑлÑки ми запÑÑкаÑмо його аÑинÑ
Ñонно, пÑÑÐ»Ñ Ð·Ð°Ð²ÐµÑÑÐµÐ½Ð½Ñ ÑозбоÑÑ HTML. Ðи можемо обÑобиÑи доÑÑÑÐ½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи, ÑкÑо поÑÑÑбно, Ñ Ð·Ð°Ð²ÐµÑÑиÑи ÑнÑÑÑалÑзаÑÑÑ.
Ð ÑнÑого бокÑ, Ñе ÑÑÑÐµÐ½Ð½Ñ Ñакож не Ñ ÑдеалÑним. ЯкÑо Ð²ÐºÐ»Ð°Ð´ÐµÐ½Ñ ÐºÐ°ÑÑÐ¾Ð¼Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи Ñакож викоÑиÑÑовÑÑÑÑ setTimeout Ð´Ð»Ñ ÑнÑÑÑалÑзаÑÑÑ, Ñо вони ÑÑаÑÑÑ Ñ ÑеÑгÑ: ÑпоÑаÑÐºÑ ÑпÑаÑÑовÑÑ Ð·Ð¾Ð²Ð½ÑÑнÑй setTimeout, а поÑÑм внÑÑÑÑÑнÑй.
Таким Ñином, зовнÑÑнÑй ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð·Ð°Ð²ÐµÑÑÑÑ ÑнÑÑÑалÑзаÑÑÑ ÑанÑÑе, нÑж внÑÑÑÑÑнÑй.
ÐÑодемонÑÑÑÑÑмо Ñе на пÑикладÑ:
<script>
customElements.define('user-info', class extends HTMLElement {
connectedCallback() {
alert(`${this.id} пÑдклÑÑено.`);
setTimeout(() => alert(`${this.id} ÑнÑÑÑалÑзовано.`));
}
});
</script>
<user-info id="outer">
<user-info id="inner"></user-info>
</user-info>
ÐоÑÑдок виведеннÑ:
- outer пÑдклÑÑено.
- inner пÑдклÑÑено.
- outer ÑнÑÑÑалÑзовано.
- inner ÑнÑÑÑалÑзовано.
Ðи баÑимо, Ñо зовнÑÑнÑй ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð·Ð°Ð²ÐµÑÑÑÑ ÑнÑÑÑалÑзаÑÑÑ (3) ÑанÑÑе, нÑж внÑÑÑÑÑнÑй (4).
Ðе ÑÑнÑÑ Ð²Ð±Ñдованого колбекÑ, Ñкий би ÑпÑаÑÑовÑвав пÑÑÐ»Ñ Ñого, Ñк Ð²ÐºÐ»Ð°Ð´ÐµÐ½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи гоÑовÑ. ЯкÑо поÑÑÑбно, ми можемо ÑеалÑзÑваÑи ÑÐ°ÐºÑ ÑÑÑ ÑамоÑÑÑйно. ÐапÑиклад, внÑÑÑÑÑÐ½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи можÑÑÑ Ð²ÑдпÑавлÑÑи подÑÑ ÑÐ¸Ð¿Ñ initialized, а зовнÑÑÐ½Ñ â ÑлÑÑ
аÑи Ñ ÑеагÑваÑи на ниÑ
.
ÐаÑÑомÑÐ·Ð¾Ð²Ð°Ð½Ñ Ð²Ð±ÑÐ´Ð¾Ð²Ð°Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи
ÐÐ¾Ð²Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи, ÑÐºÑ Ð¼Ð¸ ÑÑвоÑÑÑмо, ÑÐ°ÐºÑ Ñк <time-formatted>, не маÑÑÑ Ð¶Ð¾Ð´Ð½Ð¾Ñ Ð¿Ð¾Ð²âÑÐ·Ð°Ð½Ð¾Ñ Ð· ними ÑеманÑики. Ðони невÑÐ´Ð¾Ð¼Ñ Ð¿Ð¾ÑÑковим ÑиÑÑемам, Ñ Ð¿ÑиÑÑÑÐ¾Ñ Ð´Ð¾ÑÑÑпноÑÑÑ Ð½Ðµ можÑÑÑ ÑÑ
обÑоблÑÑи.
Ðле ÑÐ°ÐºÑ ÑеÑÑ Ð¼Ð¾Ð¶ÑÑÑ Ð±ÑÑи важливими. ÐапÑиклад, поÑÑковÑй ÑиÑÑÐµÐ¼Ñ Ð±Ñде ÑÑкаво знаÑи, Ñо ми дÑйÑно показÑÑмо ÑаÑ. Ð ÑкÑо ми Ñобимо оÑобливий Ñип кнопки, Ñо ÑÐ¾Ð¼Ñ Ð± не викоÑиÑÑаÑи ÑÑнÑÑÑий ÑÑнкÑÑонал <button>?
Ðи можемо ÑозÑиÑÑваÑи Ñа налаÑÑовÑваÑи вбÑÐ´Ð¾Ð²Ð°Ð½Ñ HTML-елеменÑи, ÑÑпадковÑÑÑи ÑÑ Ð½Ñ ÐºÐ»Ð°Ñи.
ÐапÑиклад, кнопки Ñ ÐµÐºÐ·ÐµÐ¼Ð¿Ð»ÑÑами клаÑÑ HTMLButtonElement, викоÑиÑÑаймо його.
-
РозÑиÑÑÑмо
HTMLButtonElementнаÑим клаÑом:class HelloButton extends HTMLButtonElement { /* меÑоди каÑÑомного елеменÑа */ } -
ÐеÑедаÑмо ÑÑеÑÑй аÑгÑÐ¼ÐµÐ½Ñ Ð´Ð¾
customElements.define, Ñкий визнаÑÐ°Ñ Ñег:customElements.define('hello-button', HelloButton, {extends: 'button'});ÐожÑÑÑ ÑÑнÑваÑи ÑÑÐ·Ð½Ñ Ñеги, ÑÐºÑ Ð²Ð¸ÐºÐ¾ÑиÑÑовÑÑÑÑ Ð¾Ð´Ð¸Ð½ Ñ Ñой Ñамий DOM-клаÑ, Ñаме ÑÐ¾Ð¼Ñ Ð¿Ð¾ÑÑÑбно вказÑваÑи
extends. -
ÐÑеÑÑоÑ, Ñоб викоÑиÑÑаÑи Ð½Ð°Ñ ÐºÐ°ÑÑомний елеменÑ, вÑÑавÑе звиÑайний Ñег
<button>, але додайÑе до нÑогоis="hello-button":<button is="hello-button">...</button>
ÐÑÑ Ð¿Ð¾Ð²Ð½Ð¸Ð¹ пÑиклад:
<script>
// Ðнопка, Ñка каже "пÑивÑÑ" пÑи наÑиÑканнÑ
class HelloButton extends HTMLButtonElement {
constructor() {
super();
this.addEventListener('click', () => alert("ÐÑивÑÑ!"));
}
}
customElements.define('hello-button', HelloButton, {extends: 'button'});
</script>
<button is="hello-button">ÐлаÑни мене</button>
<button is="hello-button" disabled>Ðимкнено</button>
ÐаÑа нова кнопка ÑозÑиÑÑÑ Ð²Ð±ÑдованÑ. Ð¢Ð¾Ð¼Ñ Ð²Ð¾Ð½Ð° збеÑÑÐ³Ð°Ñ ÑÑ ÑÐ°Ð¼Ñ ÑÑÐ¸Ð»Ñ Ñа ÑÑандаÑÑÐ½Ñ ÑÑнкÑÑÑ, ÑÐ°ÐºÑ Ñк аÑÑибÑÑ disabled.
ÐоÑиланнÑ
- HTML Living Standard: https://html.spec.whatwg.org/#custom-elements.
- СÑмÑÑнÑÑÑÑ: https://caniuse.com/#feat=custom-elementsv1.
ÐÑдÑÑмки
ÐаÑÑÐ¾Ð¼Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи можÑÑÑ Ð±ÑÑи Ð´Ð²Ð¾Ñ ÑипÑв:
-
âÐвÑономнÑâ â Ð½Ð¾Ð²Ñ Ñеги, Ñо ÑозÑиÑÑÑÑÑ
HTMLElement.Ð¡Ñ ÐµÐ¼Ð° визнаÑеннÑ:
class MyElement extends HTMLElement { constructor() { super(); /* ... */ } connectedCallback() { /* ... */ } disconnectedCallback() { /* ... */ } static get observedAttributes() { return [/* ... */]; } attributeChangedCallback(name, oldValue, newValue) { /* ... */ } adoptedCallback() { /* ... */ } } customElements.define('my-element', MyElement); /* <my-element> */ -
âÐаÑÑомÑÐ·Ð¾Ð²Ð°Ð½Ñ Ð²Ð±ÑÐ´Ð¾Ð²Ð°Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñиâ â ÑозÑиÑÐµÐ½Ð½Ñ ÑÑнÑÑÑÐ¸Ñ ÐµÐ»ÐµÐ¼ÐµÐ½ÑÑв.
ÐоÑÑебÑÑ Ñе одного аÑгÑменÑÑ
.defineÑаis="..."Ñ HTML:class MyButton extends HTMLButtonElement { /*...*/ } customElements.define('my-button', MyElement, {extends: 'button'}); /* <button is="my-button"> */
ÐаÑÑÐ¾Ð¼Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи добÑе пÑдÑÑимÑÑÑÑÑÑ Ð±ÑаÑзеÑами. Також ÑÑнÑÑ Ð¿Ð¾Ð»ÑÑÑл https://github.com/webcomponents/polyfills/tree/master/packages/webcomponentsjs.
ÐоменÑаÑÑ
<code>, Ð´Ð»Ñ ÐºÑлÑÐºÐ¾Ñ ÑÑдкÑв â обгоÑнÑÑÑ ÑÑ Ñегом<pre>, Ð´Ð»Ñ Ð¿Ð¾Ð½Ð°Ð´ 10 ÑÑдкÑв â викоÑиÑÑовÑйÑе пÑÑоÑниÑÑ (plnkr, jsbin, codepenâ¦)