전 시간에 CustomElement를 만드는 방법에 대해서 확인해보았다. 이번 시간부터는 조금더 상세하게 확인해보도록 하자.
정의요소
class MyElement extends HTMLElement {
constructor () {
super()
// element 생성
}
connectedCallback () {
// document에 element가 추가 되면 브라우저에서 호출이 된다.
}
disconnectedCallback () {
// document에 element가 제거 되면 브라우저에서 호출이 된다.
}
static get observedAttributes () {
return [/* 모니터링 될 속성의 이름. */]
}
attributeChangedCallback (name, oldValue, newValue) {
// observedAttributes에서 나열되어있는 속성중 하나의 속성이라도 값이 변경되면 호출 된다.
}
adoptedCallback () {
// 해당 엘리먼트라 다른 document로 이동될 시 호출 된다.
}
}
customElement를 정의하게 되면 위의 메서드들을 정의할 수 있다. 각각의 메서드들 중 constructer를 제외 하고는 처음 보는 것들일 것이다. 각각의 속성에 대해서 설명을 해보겠다.
constucter
당연 하게도, new MyElement()를 호출하게 되면 constructer가 호출되는 것은 당연하게 여길 것이다. 그 외에 엘리먼트로써 생성되는 경우가 두가지가 있다.
html 본문에 태그로 작성 되어있는 경우 customElements.define이 되어있다면, 해당 태그가 해석 될 때 constructer가 호출 되고, customElements.define가 태그 해석이 완료 후에 호출된다면, define이 되었을 때 호출이 된다.
하지만 우리가 엘리먼트을 만들수 있는 방법은 하나가 더있다. document.createElement이다. 이때 이미 define되어있는 엘리먼트라면 constructer는 호출 되지만, documente.createElement 이후에 define 된다면 constructer는 document내에 추가되는 행위가 있을 때 호출이 된다.
export class MyElement extends window.HTMLElement {
constructor () {
super()
// element 생성
console.log('init')
}
}
connectedCallback, disconnectedCallback
connectedCallback의 경우에는 지난시간에 확인하였기에, disconnectedCallback과 함께 설명을 하자.
export class MyElement extends window.HTMLElement {
connectedCallback () {
// document에 element가 추가 되면 브라우저에서 호출이 된다.
this.timeInterval = setInterval(() => {
const currentDate = new Date()
this.innerHTML = `<div>${currentDate}</div>`
console.log(currentDate)
}, 1000)
}
disconnectedCallback () {
// document에 element가 제거 되면 브라우저에서 호출이 된다.
clearInterval(this.timeInterval)
}
}
우리는 위처럼 connectedCallback 때부터 계속 시간을 새도록 만들수도 있을 것이고, 해당 엘리먼트가 제거 될 때 timer를 종료 시킬수 있다.
만약에 clearInterval을 하지 않는 다면 결과는 아래와 같다.
위 처럼 엘리먼트가 document에서 제거 되었음에도 불구하고 콘솔에 정보가 나타난다.이번에 설명할 observedAttributes, attributeChangedCallback 메서드들도, 쌍으로 이루어진 이루어진 메서드라고 보면 된다. attributeChangedCallback의 경우 observedAttributes의 값이 변경된 경우에 호출이 되기 때문이다.
사용법은 아래와 같다.
export class MyElement extends window.HTMLElement {
connectedCallback () {
this.setAttribute('name', '익명')
}
static get observedAttributes () {
return ['name']
}
attributeChangedCallback (name, oldValue, newValue) {
this.innerHTML = `<div>${newValue}님 안녕하세요.</div>`
}
}
뭐 간단한 인사말을 나타내는 엘리먼트이고 처음에는 name을 알수없는 경우를 산정해보았다.
참고로 constructer에서 setAttribute를 하는경우 변경으로 감지 되지는 않아 attributeChangedCallback이 호출 되지 않으니 참고 하도록 하자.adoptedCallback
이 메서드의 경우 자주 호출될 만한 일은 없을 것으로 판단된다. 말 그대로 다른 document로 이동이 되어야 호출 되기 때문이다. 다른 document라는 것은 iframe으로 간단하게 만들 수 있긴 하다. 사용할 일이 없길 바란다.
export class MyElement extends window.HTMLElement {
constructor () {
super()
this.adoptedCount = 0
}
render () {
return `<div>입양 횟수 : ${this.adoptedCount}</div>`
}
connectedCallback () {
this.innerHTML = this.render()
}
adoptedCallback () {
this.adoptedCount++
}
}
https://developer.mozilla.org/ko/docs/Web/API/Document/adoptNode
document.adoptNode라는 함수가 있고, 해당 함수로 다른 document가 입양을 해야 호출이 된다.
개인적으로 이번 예제를 위하여 adoptNode를 처음 호출해보았다. 해당 메서드는 언제 사용할 수 있을지도 좀 긴가민가한 상태이기 때문에 알아만 두는 것을 추천한다.
댓글
댓글 쓰기