16일

Custom Element를 extends 한 경우 class 의 getter/setter 가 동작 하지 않을수 있다. 특히 다음과 같이 DOM 객체의 property를 할당하는 구문이 있을때 해당 현상이 나타난다.


class ServerControlPanel extends $.CustomElement {
	constructor() {
		super();
	}
	async render() {
		console.log(this.serverStatus);
		render(tmpl(this), this.shadowRoot);
		
		$.get(this.shadowRoot, "server-status").status = this.serverStatus; // not call `server-status.status` setter.
	}
}

이는 Custom Elements 의 경우 defined 되기전에 사용될수 있기 때문이다. 이를 Element의 Upgrade 라고 부른다. 이때 property가 먼저 할당이 되므로 prototype(js의 class 구현체)의 property 까지 접근을 하지 않고, instance 의 property 가 먼저 사용 되는 것이다. 따라서 해당 property를 먼저 delete 해주면 문제가 임시로 해결된다.


class ServerControlPanel extends $.CustomElement {
	constructor() {
		super();
	}
	async render() {
		console.log(this.serverStatus);
		render(tmpl(this), this.shadowRoot);
		
		delete $.get(this.shadowRoot, "server-status").status; // delete property for prototype(temporary solution)
		$.get(this.shadowRoot, "server-status").status = this.serverStatus;
	}
}

물론 이는 완전한 해결책이 아니며 완전하게 해결하기 위해서는 다음과 같이 customElements.whenDefined를 사용하여 custom element 가 정의 된 이후에 해당 property를 쓰도록 해야 한다.


class ServerControlPanel extends $.CustomElement {
	constructor() {
		super();
	}
	async render() {
		console.log(this.serverStatus);
		render(tmpl(this), this.shadowRoot);

		await customElements.whenDefined("server-status"); // wait until element defined
		
		$.get(this.shadowRoot, "server-status").status = this.serverStatus;
	}
}

18일