Vanilla Js로 react랑 비슷하게 코딩하기

오준상·2020년 5월 11일
4

서론

글을 시작하기 전에, 제목을 보고 이곳에 들어온 사람들이 많을 것이다.
솔직하게 말하자면, 과장된 것 같다.
개발자가 아직 아닌 개발자를 희망하는 사람이니, 그 점 참고하고 읽어주길 바란다.
피드백과 훈수는 언제나 환영이다.❤
그럼, 이제 왜 제목을 저렇게 지었는가? (스토리 읽기 싫으면 밑에 것은 건너뛸 것을 추천)


어떻게 알았는가?

이제 react 같은 library를 보면, component를 나눠서 개발 하는 것을 볼 수 있다.
그리고 그걸 어디서든지 끌고 와서 사용 할 수 있게 한다는 것, 난 이게 너무 편리했다.
하지만, 인생을 살다가 보니 언제든지 react만 사용할 수 있는 것은 아니였다.
CRA가 아닌 custom webpack으로 bundling을 해야하는 날도 있듯이
기본 html, js를 사용해야 하는 일이 생긴 것이다.
내 손가락과 신체 리듬은 react에 맞춰져 있다. 그래서 react스럽게 html,js로 코딩하는 법을 찾다가 짜란! 잭팟. custom components와 shadow dom을 알게 되었다.


그래서 이게 뭔데?

음...간단하게 말하자면 js로 html에서 사용하는 element들을 만들어서,
html에서 쓸 수 있게 해준다..가 된다. 물론 element는 기존의 html들로 만든다.
shadow dom은 우리가 webpack을 사용하는 이유와 비슷하다.
webpack을 쓰는 이유는 bundling의 기능을 한다. 다른 파일에 있는 같은 변수가 함수명
을 사용하면 파일을 끌어 올 때, 에러가 발생할 수 있으므로, 파일명을 바꿔주는데, css에서도 class명이나 id명이 변할 수 있다. 따라서, shadow dom이라는 dom과는 다른 부분에 새로운 dom을 생성해 준다고 생각하면 편하다.

출처: https://miro.medium.com/max/1424/1*vb3-5n48rHq55qQzAN67qA.png


어떻게 사용해?

사용법은 간단하다.

<!DOCTYPE html>
<html>
    <head>
        <script src="jsfile 경로"></script>
    </head>
    <body>
        <hello-world>hello world!</hello-world>
    </body>
</html>

이런 형태의 html 파일을 생성했다고 하자.
저기 head에 script file을 불러 오게 된다.

class helloworld extends HTMLElement {
    constructor() {
        super();
    }
    static get observedAttributes() {
        // 모니터링 할 속성 이름
    }
    connectedCallback() {
        // DOM에 추가되면 실행되는 method;
        this.innerText = "hi!";
        this.set();
    }
    disconnectedCallback() {
        // DOM에서 제거면 실행되는 method
    }
    attributeChangedCallback(attrName, oldVal, newVal) {
        // 속성이 추가/제거/변경되면 실행되는 method
    }
    adoptedCallback(oldDoc, newDoc) {
        // 다른 Document에서 옮겨지면 실행되는 method
    }
    set() {
		setTimeout(()=> {
			this.innerText = "my name is indio";
        },1000)
    }
}
customElements.define('hello-world', helloworld);

이런 코드를 짜고 난 후에 html을 실행시켜 보면,
맨 처음에 hi!라고 뜨던 글씨가 1초 후에 my name is indio라고 바뀌는 것을 알 수 있다.
하지만 우리가 원하는 것은 이게 아닐꺼라고 생각한다.
이쁜 UI를 만드려면 shadow dom을 써야한다.

class MyElement extends HTMLElement {
    static get observedAttributes() {return ['lang']; }
    constructor() {
      super();
      // add shadow root in constructor
      const shadowRoot = this.attachShadow({mode: 'open'});
      shadowRoot.innerHTML = `
        <style>div { background-color: #82b74b; }</style>
        <div>yey</div>
      `;
      // style 정의 및 div 생성
      this._yey = shadowRoot.querySelector('div');
    }
    attributeChangedCallback(attr, oldValue, newValue) {
      // 여기서 lang이라는 attribute가 추가되면 if문에서 통과된다.
      if (attr == 'lang') {
        let yey;
        switch (newValue) {
          case 'ko':
            yey = '만세!';
          break;
          case 'es':
            yey = 'hooray!';
          break;
          case 'jp';
            yey = '万歳!';
          break;
          default:
            yey = 'yey!';
        }
        this._yey.innerText = yey;
      }
    }
    yell() {
      alert(this._yey.innerText);
    }
  }
  window.customElements.define('my-element', MyElement);

저런 형식으로 style과 html을 생성하여 만들 수 있다.

후기

개인적으로 좋은 기능을 알았다고 생각하며, 바닐라 js로도 이런 코딩을 할 수 있구나에
대해 엄청난 성취감을 얻었다.

출처

공부 출처 : https://kyu.io/%EC%9B%B9-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B81-keep-calm-and-usetheplatform/

profile
만들고싶은걸만듭니다

2개의 댓글

comment-user-thumbnail
2021년 7월 7일

안녕하세요 함수형 컴포넌트로도 할 수 있는건지 궁금합니다!

1개의 답글