Skip to content

Instantly share code, notes, and snippets.

@yuheiy
Last active June 4, 2017 17:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yuheiy/0167a39840143662b8e85517b8d0d5d0 to your computer and use it in GitHub Desktop.
Save yuheiy/0167a39840143662b8e85517b8d0d5d0 to your computer and use it in GitHub Desktop.
Web Componentsのなにがうれしいのか

Web Componentsのなにがうれしいのか

個人的な意見に基づく記述です

現在(Web Componentsが来る前)

  • HTML、CSS、JavaScriptをコンポーネントという単位に分解して管理する開発が主流
  • それを独自のツールやライブラリによって実現している
  • かなりコストがかかっているし、解決できない問題も多い
    • ツールやライブラリの開発、及びその学習コスト。みんな独自に違うことやってる。それが廃れたときのことも考えないといけない(しかも代謝早い)
    • CSSがコンポーネント単位に分離されていようが、あくまでセレクタはグローバル。いくらでも行儀の悪いことができる

Web Componentsが解決する問題

  • Web Componentsはより強力なコンポーネント設計を実現するためのネイティブの仕様
  • ツールやライブラリに依存しなくてもコンポーネント設計を実現しやすくなる
    • 独自のツールやライブラリに依存するよりも堅実で寿命が長くなる
  • CSSに真のスコープが導入できる
    • 追加したスタイルが思わぬところに悪影響を与えてしまう可能性を制御できる
    • 最初に書いたbase.cssを二度といじれない問題を避けられる

Web Componentsが解決できない問題

  • Web ComponentsだとViewの更新は生のDOMを書き換えることになるので、複雑なViewだとReactみたいなライブラリは引き続き欲しい(統合はできるようになってる)
  • 単にコンポーネントの実装を強化するものなので、結局実装の上流工程での設計が重要なのは変わらない

その他

  • 絶賛仕様作成途中。ES Modulesとの統合とかまだ考えられてない
  • CSSの継承はWeb Components関係なく、initialでリセットできる。ただしIE11は未対応
  • 仕様が固まるのはまだ先だけど、IEのサポートが切れるよりは早いはず。みんなで幸せになるために早くIEを撲滅させよう!

資料

<template>
<style>
:host {
all: initial;
display: inline-block;
padding: 1rem;
background-color: var(--color-bg);
border: 1px solid;
contain: content;
}
b {
font-size: 2rem;
}
</style>
<b></b>
<ul>
<li><button id="increment">increment</button></li>
<li><button id="decrement">decrement</button></li>
</ul>
</template>
<script>
;(() => {
class CounterApp extends HTMLElement {
constructor() {
super()
const shadowRoot = this.attachShadow({mode: 'open'})
const template = document.currentScript.ownerDocument.querySelector('template')
const clone = document.importNode(template.content, true)
shadowRoot.appendChild(clone)
this.count = 0
this._onClickIncrement = this._onClickIncrement.bind(this)
this._onClickDecrement = this._onClickDecrement.bind(this)
}
get count() {
return this._count
}
set count(newCount) {
this._count = newCount
this._render()
}
connectedCallback() {
this.shadowRoot.querySelector('#increment').addEventListener('click', this._onClickIncrement)
this.shadowRoot.querySelector('#decrement').addEventListener('click', this._onClickDecrement)
}
disconnectedCallback() {
this.shadowRoot.querySelector('#increment').removeEventListener('click', this._onClickIncrement)
this.shadowRoot.querySelector('#decrement').removeEventListener('click', this._onClickDecrement)
}
_render() {
this.shadowRoot.querySelector('b').textContent = this.count
}
_onClickIncrement() {
this.count++
}
_onClickDecrement() {
this.count--
}
}
customElements.define('counter-app', CounterApp)
})()
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>try web components</title>
<link rel="import" href="counter-app.html">
<style>
:root {
--color-bg: hsl(0, 0%, 80%);
}
body {
margin: 1rem;
font-family: serif;
}
b {
color: red;
}
</style>
</head>
<body>
<p><b>app</b></p>
<counter-app></counter-app>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment