WebComponent魔法堂:Custom Elementの標準構築を深く追究する.
14924 ワード
前言
『WebComponent魔法堂:Custom Elementの痛点向けプログラミングを深く追究する』を通じて、Custom Elementは別に新しいものではないことが分かりました.自分のカスタム要素は、既存の方法によって実装され得る( .は、カスタム要素・インスタンス( .は元素のライフサイクルを監督することができます.GoogleをはじめとするH 5 Custom Elementは、既存の標準要素に基づいて、上向のブラウザに様々な抽象的なレベルの高いカスタム要素を注入し、元素CRUD操作で生APIとシームレスにドッキングし、プログラミング体験がよりスムーズになります.次に、H 5 Custom Elementを通じて、 この「小さなこと」に命名します.
正式なロールコードの前に、皆さんに一番頭が痛いことは元素の命名方法です.以下の3つの要素は私達の名前に影響します.名前の衝突.カスタムコンポーネントは様々な第三者のクラスのように命名衝突の問題があるので、名前空間を導入して解決したいと自然に思いますが、コンポーネントの名前はコンポーネントのリソースローディングの問題に関わっていないので、ここで簡略化します. 意味化.意味化とは、要素名が望文生義の境界に達するということであり、例えば 十分な吊り下げ:高い名前はいつも人を喜ばせてくれます.私達のプロジェクトチームの前に、警告システムを「超無敵グローバルポジショニング来料品質」と改名すると冗談を言っています.上記3点以外にも、H 5仕様にはこの規定があります.カスタム要素は少なくとも1つのハイフンを含んでいなければなりません.つまり、最も簡単な形式もこのようにしてください.ハイフンを付けない名前はブラウザの元の要素として残して使います.言い換えれば、名前のハイフネーションの要素は有効なカスタム要素として認識され、ハイフネーションのない要素は元の要素として認識されるか、無効な要素として認識されるということです.
名前付き仕様により、カスタム要素とオリジナル要素を効果的に区別し、プレフィクスによって命名衝突問題を解決しました.ちょっと待ってください.プレフィックスを追加するのは本当にネーミングの衝突を解決するいい方法ですか?これは、プレフィクスを追加することによってIDの衝突を解決するのと同じです.命名衝突が発生した場合、プレフィクスをもう衝突しないまで延長します.JAVAの
Custoome Element v 0を操作します.
は元素に対して命名して騒がしいです.APIをする時です.
最初から足に新しい要素を定義します.
時には既存の元素の基礎の上で機能を強化したいだけです.もしまた初めからやり始めるなら、それは大変です.幸いCustom Elementの規範はもう私達のために考えられました.次にinput元素を強化します.
Custom Element APIは現在v 1バージョンにアップグレードされていますが、実際には専用のは、最初から を定義する.漸進強化
ここに来て、皆さんはもうCustom Element APIを知っていると思います.以下は完全な要素をカスタマイズしてみましょう.しかし、実際の操作の前に、私たちはまず、どのような詳細に注意すべきですか?
各段階の適切な操作を明確にする.
1...ソースの状態を初期化したり、イベントの傍受を設定したり、Shadow Domを作成したりします.2.connectedCallbackリソースの取得や要素レンダリングなどの操作はここで実行するのに適していますが、この方法は何度も呼び出されることができますので、一回だけの操作に対しては検査方案を持参します.3.disconnectedCallback 適切な協力資源の整理などの仕事(例えば、事件の傍受を除去する)
もっと細かいところ
1....ソースの詳細1.1.最初の文は、
Chrome 54はデフォルトではCustom Element v 1をサポートしていますが、Chrome 53は起動パラメータ
余談をする
Custom Elementについてはここまで話しましょう.でもここでちょっとおかしいですが、注意すべき細かい問題を提出します.つまり、カスタム要素は必ず Void elementsフォーマットは Raw text elemensフォーマットは を含む. escapable raw text elementsフォーマットは を含む. Foreign elemensフォーマットは である. Normal elemensフォーマットは 締め括りをつける
心からCustom Elementを聞いた時、私はとても興奮していました.まるで命の藁を見つけたかのようです.しかし、他の新しい技術の出現と同じように、利害が同業して、どうやって判断して利用するかは頭が痛いことです.先人の経験が方向を教えてくれるかもしれません.次の「WebComponent魔法堂:Custom Elementを深く追究し、過去から現在を見る」では、18年前にタイムスリップし、パイオニアHTML Componentの黒い歴史を見て、再びWebComponentを見ましょう. オリジナルを尊重し、転載は下記の通り明記してください.http://www.cnblogs.com/fsjohn... ^_^太ったジョンさん
感謝します
How to Create Custom HTML Elements A vocabulary and assicated API for HTML and XHTMLCustom Elements v 1 custom-elemens-custom-builtin-example
『WebComponent魔法堂:Custom Elementの痛点向けプログラミングを深く追究する』を通じて、Custom Elementは別に新しいものではないことが分かりました.自分の
alert
元素をIE 5.5に定義することもできます.しかし、このような簡単で粗暴なカスタム要素は必要ではありません.以下の特徴を持つカスタム要素が必要です.
、new CustomElement()
、document.createElement('CUSTOM-ELEMENT')
)document.body.appendChild
など、CSSスタイルによって修飾されることができるなど)を従来の方法で操作することができるalert
要素を再定義しましょう.正式なロールコードの前に、皆さんに一番頭が痛いことは元素の命名方法です.以下の3つの要素は私達の名前に影響します.
com-cnblogs-fsjohnhuang-alert
は、プレフィクスであることを知っているように見える.要素の機能に関係なく、x-alert
は元素の機能である.const compose = (...fns) => {
const lastFn = fns.pop()
fns = fns.reverse()
return a => fns.reduce((p, fn) => fn(p), lastFn(a))
}
const info = msg => console.log(msg)
const type = o => Object.prototype.toString.call(o)
const printType = compose(info, type)
const newElem = tag => document.createElement(tag)
//
const xAlert = newElem('x-alert')
infoType(xAlert) // [object HTMLElement]
//
const alert = newElem('alert')
infoType(alert) // [object HTMLUnknownElement]
//
const div = newElem('div')
infoType(div) // [object HTMLDivElement]
じゃ、私はあえてx
を使って定義要素から来ますか?ブラウザで「悟空、またやんちゃ」と言ってもいいです.名前付き仕様により、カスタム要素とオリジナル要素を効果的に区別し、プレフィクスによって命名衝突問題を解決しました.ちょっと待ってください.プレフィックスを追加するのは本当にネーミングの衝突を解決するいい方法ですか?これは、プレフィクスを追加することによってIDの衝突を解決するのと同じです.命名衝突が発生した場合、プレフィクスをもう衝突しないまで延長します.JAVAの
alert
という名前が出てくる可能性があります.騒音は明らかに多く、直接的に意味化の程を下げることができます.タイピングの疲れは見ても疲れます.このすべての根源は、Schope-Global Scopeだけであり、したがって、名前の衝突を解決するための付加的な情報はコンテキストを通じて暗黙的に提供できなくなり、直接にプレフィックスによってハードに追加される必要があります. プレフィックスの方式は認めましたが、字を書かないようにしてもいいですか?名前空間のように名前が衝突した時があります.#!usr/bin/env python
# -*- coding: utf-8 -*-
from django.http import HttpResponse
def index(request):
return HttpResponse('Hello World!')
名前の衝突がある場合#!usr/bin/env python
# -*- coding: utf-8 -*-
import django.db.models
import peewee
type(django.db.models.CharField)
type(peewee.CharField)
プレフィックスも選択の省略があればいいです.Custoome Element v 0を操作します.
は元素に対して命名して騒がしいです.APIをする時です.
最初から足に新しい要素を定義します.
/** x-alert **/
const xAlertProto = Object.create(HTMLElement.prototype, {
/* */
//
createdCallback: {
value: function(){
console.log('invoked createCallback!')
const raw = this.innerHTML
this.innerHTML = `
${raw}
`
this.querySelector('button.close').addEventListener('click', _ => this.close())
}
},
// DOM
attachedCallback: {
value: function(){
console.log('invoked attachedCallback!')
}
},
// DOM
detachedCallback: {
value: function(){
console.log('invoked detachedCallback!')
}
},
// attribute
attributeChangedCallback: {
value: function(attrName, oldVal, newVal){
console.log(`attributeChangedCallback-change ${attrName} from ${oldVal} to ${newVal}`)
}
},
/* */
// textContent
textContent: {
get: function(){ return this.querySelector('.content').textContent },
set: function(val){ this.querySelector('.content').textContent = val }
},
close: {
value: function(){ this.style.display = 'none' }
},
show: {
value: function(){ this.style.display = 'block' }
}
})
//
const XAlert = document.registerElement('x-alert', { prototype: xAlertProto })
/** **/
//
const xAlert1 = new XAlert() // invoked createCallback!
const xAlert2 = document.createElement('x-alert') // invoked createCallback!
// DOM
document.body.appendChild(xAlert1) // invoked attachedCallback!
// DOM
xAlert1.remove() // invoked detachedCallback!
// DIV , DOM attachedCallback detachedCallback
const d = document.createElement('div')
d.appendChild(xAlert1)
xAlert1.remove()
//
xAlert1.textContent = 1
console.log(xAlert1.textContent) // 1
xAlert1.close()
//
xAlert1.setAttribute('d', 1) // attributeChangedCallback-change d from null to 1
xAlert1.removeAttribute('d') // attributeChangedCallback-change d from 1 to null
// setAttributeNode removeAttributeNode attributeChangedCallback
上記のa-b
要素を定義することにより、Custom ElementのすべてのAPIが示されているが、alert
インターフェースを継承した後、4つのライフサイクルのコールバック方法を選択的に実現し、com-cnblogs-fsjohnhuang-alert
にカスタム要素コンテンツ展開の論理が書かれている.また、要素の公開属性と方法を定義することができる.最後にx-alert
方法を通じて、ブラウザに新しい要素を定義したことを知らせます. 今の問題はHTMLElement
このHTML MarkpがcreatedCallback
コールの前に現れたら、どんな状況がありますか?このときのdocument.registerElement
要素は、unresoloved状態にあり、CSS Selector
によって捕捉されてもよく、document.registerElement
を実行すると、x-alert
要素は、resoved状態にある.このように、2つの状態に対してスタイル調整ができます.アンレスレベルの状態を知らせる要素はまだ使えません.ご期待ください.
漸進的にオリジナル要素を強化する時には既存の元素の基礎の上で機能を強化したいだけです.もしまた初めからやり始めるなら、それは大変です.幸いCustom Elementの規範はもう私達のために考えられました.次にinput元素を強化します.
const xInputProto = Object.create(HTMLInputElement.prototype, {
createdCallback: {
value: function(){ this.value = 'x-input' }
},
isEmail: {
value: function(){
const val = this.value
return /[0-9a-zA-Z]+@\S+\.\S+/.test(val)
}
}
})
document.registerElement('x-input', {
prototype: xInputProto,
extends: 'input'
})
//
const xInput1 = document.createElement('input', 'x-input') //
console.log(xInput1.value) // x-input
console.log(xInput1.isEmail()) // false
Custom Element v 1——着替えるだけです.Custom Element APIは現在v 1バージョンにアップグレードされていますが、実際には専用の
:unresolved
を入口として統一的に管理し、ユーザー定義要素を操作し、ES 6 classに対してより友好的な方法で要素を定義しています.その中のステップと概念はあまり変化していません.以下はCustom Element v 1のAPIを使って上記の二つの例を書き直します.class XAlert extends HTMLElement{
// v0 createdCallback, v0 createdCallback resolved , v1 constructor undefined , connectedCallback
constructor(){
super() //
const raw = this.innerHTML
this.innerHTML = `
${raw}
`
this.querySelector('button.close').addEventListener('click', _ => this.close())
}
// v0 attachedCallback
connectedCallback(){
console.log('invoked connectedCallback!')
}
// v0 detachedCallback
disconnectedCallback(){
console.log('invoked disconnectedCallback!')
}
// v0 attributeChangedCallback, observedAttributes
attributeChangedCallback(attrName, oldVal, newVal){
console.log(`attributeChangedCallback-change ${attrName} from ${oldVal} to ${newVal}`)
}
// attributeChangedCallback ,
static get observedAttributes(){ return ['disabled'] }
// , document.adoptNode ownerDocument
adoptedCallback(){
console.log('invoked adoptedCallback!')
}
get textContent(){
return this.querySelector('.content').textContent
}
set textContent(val){
this.querySelector('.content').textContent = val
}
close(){
this.style.display = 'none'
}
show(){
this.style.display = 'block'
}
}
customElements.define('x-alert', XAlert)
class XInput extends HTMLInputElement{
constructor(){
super()
this.value = 'x-input'
}
isEmail(){
const val = this.value
return /[0-9a-zA-Z]+@\S+\.\S+/.test(val)
}
}
customElements.define('x-input', XInput, {extends: 'input'})
//
document.createElement('input', {is: 'x-input'})
new XInput()
これ以外のunresoloved状態はdefinedおよびundefined状態に変更され、CSS対応のセレクタはdocument.registerElement
およびx-alert
である.また、window.customElements
方法を追加して、undefinedからdefinedに変換されたイベントを傍受することができます.
Twitter
Facebook
G+
// Fetch all the children of that are not defined yet.
let undefinedButtons = buttons.querySelectorAll(':not(:defined)');
let promises = [...undefinedButtons].map(socialButton => {
return customElements.whenDefined(socialButton.localName);
));
// Wait for all the social-buttons to be upgraded.
Promise.all(promises).then(() => {
// All social-button children are ready.
});
ちょうど使える元素を最初から定義するのは難しいです.ここに来て、皆さんはもうCustom Element APIを知っていると思います.以下は完全な要素をカスタマイズしてみましょう.しかし、実際の操作の前に、私たちはまず、どのような詳細に注意すべきですか?
各段階の適切な操作を明確にする.
1...ソースの状態を初期化したり、イベントの傍受を設定したり、Shadow Domを作成したりします.2.connectedCallbackリソースの取得や要素レンダリングなどの操作はここで実行するのに適していますが、この方法は何度も呼び出されることができますので、一回だけの操作に対しては検査方案を持参します.3.disconnectedCallback 適切な協力資源の整理などの仕事(例えば、事件の傍受を除去する)
もっと細かいところ
1....ソースの詳細1.1.最初の文は、
:defined
を呼び出して、親のインスタンスの作成を保証しなければならない1.2.:not(:defined)
文がないかどうか、またはcustomeElements.whenDefined({String} tagName):Promise
またはsuper()
1.3でなければならない.return
およびreturn
方法1.4を呼び出すことができない.要素の特性(atribute)とサブ要素にアクセスしないでください.要素はundefined状態にあるかもしれないので、特性およびサブ要素がなくても1.5にアクセスできます.要素の特性とサブ要素は設定しないでください.これは、たとえ要素がdefined状態であっても、return this
およびdocument.write
によって要素インスタンスを作成するときに、本来は特性とサブ要素がないはずの2.focusable要素by tabindex特性 デフォルトの場合、カスタム要素はフォーカスを取得できないため、明示的にdocument.open
の特性を追加してfocusableを有効にする必要があります.また、要素document.createElement
がnew
である場合は、要素unfocusableを除去しなければならない.3.ARIA特性 ARIA特性により、他のリーダー等の他のアクセスツールにユーザー定義要素を識別することができます.4.イベントタイプ変換 は、tabindex
を介してイベントを捕捉し、disabled
を介してイベントを開始することによってイベントタイプを変換し、より要素の特徴に合致するイベントタイプをトリガする.true
を絞りましょう.class XBtn extends HTMLElement{
static get observedAttributes(){ return ['disabled'] }
constructor(){
super()
this.addEventListener('keydown', e => {
if (!~[13, 32].indexOf(e.keyCode)) return
this.dispatchEvent(new MouseEvent('click', {
cancelable: true,
bubbles: true
}))
})
this.addEventListener('click', e => {
if (this.disabled){
e.stopPropagation()
e.preventDefault()
}
})
}
connectedCallback(){
this.setAttribute('tabindex', 0)
this.setAttribute('role', 'button')
}
get disabled(){
return this.hasAttribute('disabled')
}
set disabled(val){
if (val){
this.setAttribute('disabled','')
}
else{
this.removeAttribute('disabled')
}
}
attributeChangedCallback(attrName, oldVal, newVal){
this.setAttribute('aria-disabled', !!this.disabled)
if (this.disabled){
this.removeAttribute('tabindex')
}
else{
this.setAttribute('tabindex', '0')
}
}
}
customElements.define('x-btn', XBtn)
どうやってCustom Element v 1を使い始めますか?Chrome 54はデフォルトではCustom Element v 1をサポートしていますが、Chrome 53は起動パラメータ
tabindex
を変更する必要があります.他のブラウザではwebcomponets.jsというpolyfillが使えます.余談をする
Custom Elementについてはここまで話しましょう.でもここでちょっとおかしいですが、注意すべき細かい問題を提出します.つまり、カスタム要素は必ず
addEventListener
を使って声明しますか?dispathEvent
またはx-btn
の方式を採用してもいいですか?答えはだめです.カスタム要素はNormal Elementに属していますので、chrome --enable-blink-features=CustomElementsV1
というスタートラベルと閉じたラベルを採用して声明しなければなりません.では何がNormal Elementですか?実は元素は以下の5種類に分けられています.
であり、以下の要素
、
、
、
、area
、base
、br
、col
、embed
、hr
、img
、keygen
、link
、244579142、meta
、param
、source
、24454545454545454545454545454545454545454545454545454545454545454545454545454545454545track
であり、以下の要素wbr
、
script
であり、以下の要素style
、
textarea
、MathMLおよびSVG名前空間の要素title
で、上記4つの要素以外の要素です.いくつかの条件の下では終了ラベルを省略してもいいです.ブラウザは自動的に補完してくれますが、結果はよく軌道に乗りますので、自分で書いたほうが安全です.心からCustom Elementを聞いた時、私はとても興奮していました.まるで命の藁を見つけたかのようです.しかし、他の新しい技術の出現と同じように、利害が同業して、どうやって判断して利用するかは頭が痛いことです.先人の経験が方向を教えてくれるかもしれません.次の「WebComponent魔法堂:Custom Elementを深く追究し、過去から現在を見る」では、18年前にタイムスリップし、パイオニアHTML Componentの黒い歴史を見て、再びWebComponentを見ましょう. オリジナルを尊重し、転載は下記の通り明記してください.http://www.cnblogs.com/fsjohn... ^_^太ったジョンさん
感謝します
How to Create Custom HTML Elements A vocabulary and assicated API for HTML and XHTMLCustom Elements v 1 custom-elemens-custom-builtin-example