vanilla-component

use component structure in repeated behavior of view

Usage no npm install needed!

<script type="module">
  import vanillaComponent from 'https://cdn.skypack.dev/vanilla-component';
</script>

README

Vanilla Component

바닐라 JS(Pure JS) 환경에서 generator 문법을 이용해서 컴포넌트 기반의 구조화를 가능케 한다.
컴포넌트의 역할을 다음과 같이 단순화 및 추상화한다.

  • 렌더링: DOM 에 그려진다.
  • 이벤트 바인딩: 컴포넌트 내의 특정 요소에 이벤트 바인딩이 가능하다.
  • 데이터 정적 바인딩: 렌더링 이전에 정적인 데이터를 바인딩한다.
  • 데이터 동적 바인딩: 렌더링 이후에 동적으로 데이터를 바인딩한다.
  • 컴포넌트 트리구조 추상화: 상위 컴포넌트 렌더링시 하위 컴포넌트도 자동 렌더링된다.

1. 시작하기

컴포넌터 설계 > 생성 > 렌더링의 절차를 가진다.

import vc from 'vanilla-component';

// 컴포넌트 정의하기(추상화된 뷰)
const Box = vc.define(function* (data) {
    return vc.create(`
    <div class="box">
        <a href="#" class="link">${data.text}</a>
    </div>
    `);
});

// 컴포넌트 생성하기(구체화된 뷰)
// 생성 시 정적 데이터 바인딩할 데이터를 넣어준다.
const box = Box.create({ text: 'Hello World' });

// 렌더링하기
vc.render(box, document.getElementById('wrap'));

2. 이벤트 바인딩하기

delegation 을 이용하며 다음과 같은 문법으로 사용한다.

// 위에서 생성된 box 를 이용한다고 가정한다.
// .box 에 이벤트 핸들러를 등록한다.
box.on('click', function handleBox(event) {
    console.log(event.target);
});
// .link 에 이벤트 핸들러를 등록한다.
box.on('click', '.link', function handleBoxLink(event) {
    console.log(event.target.innerText);
});

내부적으로 bubbling 이벤트를 사용하며, event.stopPropagation()을 하도록 설계되어있다.
따라서 자식 컴포넌트에서 이벤트가 발생했을 때, 부모컴포넌트의 이벤트까지 불리지 않는다.

3. 데이터 동적 바인딩하기

동적 바인딩할 요소에 data-mutate 속성을 다음의 문법으로 넣어준다.
data-mutate="key=($variable),key=($variable),..."

import vc from 'vanilla-component';

const Box = vc.define(function* (data) {
    // box 에 style 속성을 동적으로 $style 변수로 바인딩한다.
    // box 에 text 속성(innerText)를 $text 변수로 바인딩한다.
    return vc.create(`
    <div class="box" data-mutate="style=($style),text=($text)">
        ${data.initialText}
    </div>
    `);
});
const box = Box.create({ initialText: 'text is static' });

vc.render(box, document.getElementById('wrap'));

// box 의 텍스트 속성을 동적 바인딩한다.
box.mutate({
    $style: 'border: 1px solid #333;',
    $text: 'text is mutated'
});

4. 컴포넌트 트리 구조 만들기

4-1. 컴포넌트 트리 렌더링

부모 컴포넌트 렌더링 시 자식컴포넌트도 모두 자동으로 렌더링된다.
yield 키워드를 이용해서 자식 컴포넌트를 정의해준다.
정의한 컴포넌트를 template literal 에 넣어주면 자동으로 렌더링된다.

import vc from 'vanilla-component';

const Child = vc.define(function* (data) {
    return vc.create(`
    <div class="child">
        <span>${data.given}</span>
        <span>${data.text}</span>
    </div>
    `);
});

const Parent = vc.define(function* (data) {
    // 자식 컴포넌트들을 정의한다.
    // 부모가 받은 데이터를 자식에게 전달해줄 수있다.
    const childFirst = yield Child.create({
        text: 'first child',
        given: data.given
    });
    const childSecond = yield Child.create({
        text: 'second child',
        given: data.given
    });

    return vc.create(`
    <div class="parent">
        ${childFirst}
        ${childSecond}
    </div>
    `);
});

const parent = Parent.create({ given: 'parent' });

vc.render(parent, document.getElementById('wrap'));

4-2. 부모 컴포넌트를 통해 자식컴포넌트 접근

yield한 순서대로 인덱스로 접근 가능하다.

// 위의 예제에서 parent 에서 자식 컴포넌트에 접근한다고 가정한다.
parent.children[0]; // childFirst
parent.children[1]; // childSecond