export default class Component {
$node; // 내 돔
$target; // 부모 돔
props; // 부모에게 받은 데이터
state; // 나의 상태
constructor($target, props) {
this.$target = $target; // 부모 돔 저장
this.props = props; // props 저장
this.setup(); // 초기 셋팅
this.render(); // 렌더링(돔 생성)
this.setEvent(); // 돔에 이벤트 부착
this.fetch(); // 외부 데이터 불러온 후, 그 값으로 리렌더링
}
// 주로 상태를 셋팅한다
setup() {
return;
}
// 내 돔을 생성한다
createNode(tagName) {
this.$node = createElement(tagName);
}
// 내 돔이나 부모 돔에 삽입할 마크업을 한다.
template() {
return;
}
// 자식 컴포넌트를 연결한다.
mounted() {
return;
}
// 부모 돔에 이벤트를 건다(이벤트 위임이 목적)
addEventToTarget(eventType, selector, callback) {
const children = [...Array.from(this.$target.querySelectorAll(selector))];
const isTarget = target => {
if (target instanceof HTMLElement) {
return children.includes(target) || target.closest(selector);
}
};
this.$target.addEventListener(eventType, event => {
if (!isTarget(event.target)) return false;
callback(event);
});
}
// 내 돔이나 자식 돔에 이벤트를 건다.
setEvent() {
return;
}
// template에 작성한 마크업을 내 돔이나 자식 돔에 삽입한다.
// mounted()함수를 실행해 자식 컴포넌트를 연결한다.
render() {
if (this.$node) {
this.$node.innerHTML = this.template();
this.$target.appendChild(this.$node);
} else {
this.$target.innerHTML = this.template();
}
this.mounted();
}
// 자식 컴포넌트만 리렌더링 하는 경우의 로직을 작성한다.
reRender() {
return;
}
// 상태를 변경한 후 리렌더링을 한다.
// 1. 내 컴포넌트 자체를 리렌더링 하는 경우
// 2. 특정 자식 컴포넌트만 리렌더링 하는 경우 (두 번째 인자에 true설정)
setState(newState, reRender = false) {
this.state = { ...this.state, ...newState };
reRender ? this.reRender() : this.render();
}
}
// 외부 데이터를 불러와서 setState를 실행시킨다.
fetch() {
return;
}
부모 컴포넌트에 자식 컴포넌트를 연결할 빈 태그를 만들어서 연결하고, data-component라는 속성을 넣어준다.
template() {
return `
<div class="sidebar_contents_wrap">
<div data-component="PageList" class="pages_outliner"></div>
<div data-component="AddButton"></div>
</div>
`;
}
되도록 변경사항이 있는 자식 컴포넌트만 리렌더링 시킨다.
외부 영향을 미치는 코드나 메서드는 가상 상위 컴포넌트(페이지)에서 모든 로직을 다루고, 자식 컴포넌트에게 데이터와 핸들러 메소드를 넘겨준다.
자식 컴포넌트의 메소드를 꺼내 써야할 때에는 mounted메소드에서
새로운 프로퍼티를 선언해 자식 컴포넌트의 인스턴스를 저장한다.
mounted() {
const $pageList = this.$target.querySelector('[data-component="PageList"]');
const $addButton = this.$target.querySelector('[datacomponent="AddButton"]',
);
// 리렌더링을 위해 메소드를 꺼내 써야할 자식 컴포넌트
this.PageList = new PageList($pageList, {
...
});
// 리렌더링이 필요 없는 자식
new AddButton($addButton, {
...
});
}