1. このページの目的
Web Components のサンプルを実装してみる。
その際、カスタム属性を利用する。
2. デモ
実行結果
コード
<my-elm interval="1"></my-elm>
- カスタム属性を使っていた。
class MyElm extends HTMLElement {
//static get observedAttributes() {
// return ['interval'];
//}
constructor() {
super();
// メソッド内で this を使う場合は必要
this._onIncClick = this._onIncClick.bind(this);
this._onDecClick = this._onDecClick.bind(this);
this._onIntervalIncClick = this._onIntervalIncClick.bind(this);
this._onIntervalDecClick = this._onIntervalDecClick.bind(this);
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = `
<style>
:host {
display: block;
contain: content;
}
p.title {
font-size: 1.2em;
font-weight: bold;
margin-top: 0;
}
p[name=output] {
color: blue;
margin-left: 1.5em;
}
span[name=interval] {
display: inline-block;
margin-right: 1em;
}
button {
cursor: pointer;
}
</style>
<p class="title">数字を増減させる</p>
<p name="output"></p>
<button name="inc">増</button> <button name="dec">減</button>
<hr>
Interval 属性値: <span name="interval"></span><button name="incInterval">増</button> <button name="decInterval">減</bu
tton>
`;
this._count = 0;
this._output = this.shadowRoot.querySelector('p[name=output]');
this._btnInc = this.shadowRoot.querySelector('button[name=inc]');
this._btnDec = this.shadowRoot.querySelector('button[name=dec]');
this._intervalElm = this.shadowRoot.querySelector('span[name=interval]');
this._btnIntervalInc = this.shadowRoot.querySelector('button[name=incInterval]');
this._btnIntervalDec = this.shadowRoot.querySelector('button[name=decInterval]');
this._btnInc.addEventListener('click', this._onIncClick);
this._btnDec.addEventListener('click', this._onDecClick);
this._btnIntervalInc.addEventListener('click', this._onIntervalIncClick);
this._btnIntervalDec.addEventListener('click', this._onIntervalDecClick);
}
connectedCallback() {
this._output.textContent = `0`;
if (!Number.isInteger(this.interval)) {
this.interval = 1;
}
this._intervalElm.textContent = this.interval;
}
disconnectedCallback() {
if (this._btnInc) {
this._btnInc.removeEventListener('click', this._onIncClick);
}
if (this._btnDec) {
this._btnDec.removeEventListener('click', this._onDecClick);
}
if (this._btnIntervalInc) {
this._btnIntervalInc.removeEventListener('click', this._onIntervalIncClick);
}
if (this._btnIntervalDec) {
this._btnIntervalDec.removeEventListener('click', this._onIntervalDecClick);
}
}
set interval(value) {
this.setAttribute('interval', value);
this._intervalElm.textContent = this.interval;
}
get interval() {
return parseInt(this.getAttribute('interval'));
}
_onIncClick() {
this._count += this.interval;
this._output.textContent = `${this._count}`;
}
_onDecClick() {
this._count -= this.interval;
this._output.textContent = `${this._count}`;
}
_onIntervalIncClick() {
this.interval += 1;
}
_onIntervalIncClick() {
this.interval += 1;
}
_onIntervalDecClick() {
this.interval -= 1;
}
//attributeChangedCallback(name, oldValue, newValue) {
// console.log('attributeChangedCallback()', name, oldValue, newValue);
// //this[name] = newValue;
//}
}
window.customElements.define('my-elm', MyElm);
- カスタムな属性は、値として文字列しか保持できない。
3. メモ
- Shadow DOM を使うと、カスタムオブジェクト自体の
innerHTML
は使えなくなるようだ。 - プロパティの型は文字列のみ。これは不便。
4. 参考
- なし