[TIL]構成部品


素子で考える


以前はVanilla JSを利用して簡単なTOYプロジェクトを行った経験がありましたが、今から見ればVanilla JSだけで非常に無知な方法でコードを書いています...😥
後で再設計し、ボタンを使用する簡単な例で比較します.

コマンド実装


まずボタンを作成し、ボタンの背景色を変更するコードを表示します.
const $app = document.querySelector('.app');
const $button = document.createElement('button');
$button.textContent = 'Button';
$app.appendChild($button);

const handleButton = $button => {
  if ($button.style.background === '') {
    $button.style.background = 'yellow';
  } else {
    $button.style.background = '';
  }
}

$button.addEventListener('click', e => {
  handleButton(e.target);
});
見た目は悪くないけど・・・ボタンの数を増やしたらどうですか?
const $app = document.querySelector('.app');

const $button1 = document.createElement('button');
$button1.textContent = 'Button 1';

const $button2 = document.createElement('button');
$button2.textContent = 'Button 2';

const $button3 = document.createElement('button');
$button3.textContent = 'Button 3';

$app.appendChild($button1);
$app.appendChild($button2);
$app.appendChild($button3);

const $buttons = document.querySelectorAll('.app button');

const handleButton = $button => {
  if ($button.style.background === '') {
    $button.style.background = 'yellow';
  } else {
    $button.style.background = '';
  }
}

$buttons.forEach($button => {
  $button.addEventListener('click', e => {
    handleButton(e.target);
  })
})

わあ、
動作は自分の意思で行うが,ボタン数の増加に伴い,ボタンの生成と追加にハードコーディングを行う.
単純な機能しか問題ありませんが、ボタンごとに追加されるイベントの種類が異なるか、異なる機能が必要な場合は、コードがより複雑になります.
では、構成部品として実施される例を見てみましょう.

コンポーネント方式で実装


コマンド型で実装されたコードと同じ動作をする抽象ボタンのコンポーネントを作成します.
const $app = document.querySelector('.app');

function ButtonComponent({ $target, text }) {
  if (!new.target) {
    return new ButtonComponent({ $target, text });
  }

  const $button = document.createElement('button');
  $target.appendChild($button);

  this.state = {
    toggled: false
  }

  this.setState = nextState => {
    this.state = nextState;
    this.render();
  }

  this.handleButton = () => {
    this.setState({
      toggled: !this.state.toggled
    })
  }

  this.render = () => {
    $button.textContent = text;
    $button.style.background = this.state.toggled ? 'yellow' : '';
  }

  $button.addEventListener('click', this.handleButton);
  this.render();
}

new ButtonComponent({ $target: $app, text: 'button1'});
new ButtonComponent({ $target: $app, text: 'button2'});
new ButtonComponent({ $target: $app, text: 'button3'});
このコードには修正が必要な点がたくさんありますが、上記のコマンド式で実現したコードと同じ動作をします.
これにより、コンポーネントとして実現され、拡張が容易で、読みやすいだけでなく、再利用が容易になります.