すでに持っているHTMLでUIコンポーネントを構築します。
2kb gziptと6kbのマイニー! ?
data属性をドロップします < div data-component =" Counter " >
< p data-bind =" state:Counter.count " > 0 </ p >
< button data-action =" click->Counter.decrement " >
-1
</ button >
< button data-action =" click->Counter.increment " >
+1
</ button >
</ div >classコンポーネントを作成しますか? import { Component } from "domponent" ;
export default class Counter extends Component {
constructor ( el ) {
super ( el ) ;
}
increment ( ) {
this . setState ( { count : this . state . count + 1 } ) ;
}
decrement ( ) {
this . setState ( { count : this . state . count - 1 } ) ;
}
} import { Init } from "domponent" ;
import Counter from "./Counter.js" ;
const config = {
selector : document . getElementById ( "root" ) ,
components : {
Counter
} ,
appCreated : callbackFunction
} ;
new Init ( config ) ;そして、あなたは行ってもいいです!
このライブラリは、プレレンダリングHTMLをUIコンポーネントに変えるためのクリーンでモダンな方法を設定します。このスクリプトの一部の規則を使用して、データバインディング、範囲を処理し、データを渡し、コンポーネントを作成することができます。それは、少しの反応風味(ライフサイクル方法、小道具、コンポーネント状態)を持つ刺激JSの非常に非常に軽量な代替品であることを意図しています。
Domponentは、クライアント側のレンダリングをボックスから処理せず、仮想DOMを作成せず、DOMをDIFFで作成しません(ただし、Diff StateとPropsは実行されます)。ルーティングやアプリケーションの状態全体を処理することを意図したものではありません。これは、HTMLフラグメント(Thymeleaf、Rails、Pug、使用するテンプレートエンジン)を使用して、コンポーネントの形で再利用可能な機能を作成することを目的としています。
Domponentは、いくつかの点でノックアウトに似ています。
Knockoutjsとは異なり、domponent:
ノックアウト
HTML
< p > First name: < input data-bind =" value: firstName " /> </ p >
< p > Last name: < input data-bind =" value: lastName " /> </ p >
< h2 > Hello, < span data-bind =" text: fullName " > </ span > ! </ h2 >JS
var ViewModel = function ( first , last ) {
this . firstName = ko . observable ( first ) ;
this . lastName = ko . observable ( last ) ;
this . fullName = ko . pureComputed ( function ( ) {
return ` ${ this . firstName ( ) } ${ this . lastName ( ) } ` ;
} , this ) ;
} ;
ko . applyBindings ( new ViewModel ( "Planet" , "Earth" ) ) ;domponent
HTML
< div data-component =" Hello " data-state =" { " firstName ": "Planet", "lastName": "Earth"}" >
< p > First name: < input data-action =" input->Hello.setFirstName " /> </ p >
< p > Last name: < input data-action =" input->Hello.setLastName " /> </ p >
< h2 > Hello, < span data-bind =" state:Hello.fullName " > </ span > ! </ h2 >
</ div >JS
import { Component } from "domponent" ;
export default class Hello extends Component {
constructor ( conf ) {
super ( conf ) ;
}
setFirstName ( event ) {
this . setState ( { firstName : event . target . value } , ( ) => {
this . setFullName ( ) ;
} ) ;
}
setLastName ( event ) {
this . setState ( { lastName : event . target . value } , ( ) => {
this . setFullName ( ) ;
} ) ;
}
setFullName ( ) {
this . setState ( {
fullName : ` ${ this . state . firstName } ${ this . state . lastName } `
} ) ;
}
}https://tamb.github.io/domponent/
TODOリスト:https://codesandbox.io/embed/domponent-todo-with-undo-redo-sp3s2?fontsize=14
ローカルデモ
git clonenpm installnpm run build:html-devまたはnpm run build:html-prod npm install -- save domponentこのファイルdomponent/dist/domponent.es5.production.min.jsをインポートすることで、ES5バージョンを使用できます。
トランスピラーを使用していない場合は、ES5 UMDを使用することをお勧めします。 JSDelvrリンクは次のとおりです。
// production
< script type = "text/javascript" src = "https://cdn.jsdelivr.net/npm/domponent@VERSION/dist/domponent.es5.production.min.js" defer > </ script >
// development
< script type = "text/javascript" src = "https://cdn.jsdelivr.net/npm/domponent@VERSION/dist/domponent.es5.development.min.js" defer > < / script >注:このライブラリを必要に応じて使用してください。これを使用して、 data-component 、 data-ref 、 data-ref-array属性のみに使用して、DOMの選択をより簡単にすることができます。 Exponentクラスでステートレスコンポーネントを作成できます。空は限界です。そのコアでは、domponentはHTMLのユーティリティクラスのセットです。
data-componentこの悪い男の子を使用して、コンポーネント名をInit構成オブジェクトの対応するclassに一致させます
例:HTMLがdata-component="Counter"の場合| Counterと呼ばれる構成にコンポーネントが必要です
data-bind stateまたはpropsを要素のtextContentにバインドします。まず、 state propsバインドするかどうかを指定しますdata-bind="state:Counter.count" or data-bind="props:Counter.count" :左半分にバインドするかどうかを指定します。
data-actionコンポーネントメソッドを使用してDOMイベントをバインドします。以下を検討してください。
< button data-action =" click->Counter.increment " >
+1
</ button >左半分: domイベントが聴くための文字通りの文字列を表します。右半分はコンポーネントメソッドに対応します
注:パイプで複数のリスナーを追加できます|例:
< button data-action =" click->Counter.increment|mouseover->Counter.anotherMethod " >
+1
</ button > eventListenerオプションも渡すことができます。オプションは次のようにする必要があります.クラスメソッドの後。オプションはコンマで分離する必要があります,
< button
data-action =" click->Counter.increment.passive,capture|mouseover->Counter.anotherMethod.once,passive "
>
+1
</ button > data-stateメモリ内の特定の状態でコンポーネントをインスタンス化する場合は、コンポーネントのルート要素にdata-state属性を添付する必要があります。
<div data-component="Counter" data-state='{"count":24, "isEven": true}'>
...
</div>
それは正しい。 data-state有効なJSONオブジェクトを採用します。
data-ref DOM要素を参照する必要がある場合は、次のようなdata-refを使用できます。
< div data-ref =" Counter.myElement " > </ div >どのコンポーネントがオンになっているかを序文を序文する必要があります。次に、コンポーネント$refsオブジェクトに保存されます。
その後、これを使用してCounterの要素にアクセスできますthis.$refs.myElementコンポーネントインスタンス内。
data-ref-arrayこの方法で、コンポーネントに一連の要素を作成できます。
< div data-ref-array =" Counter.elements " > </ div >
< div data-ref-array =" Counter.elements " > </ div >次に、コンポーネント$refsオブジェクトに保存されます。 this.$refs.elements 。
data-keyこれは完全にオプションです。コンポーネントインスタンスごとに一意の文字列です。
これは、小道具を結合するために内部的に使用されます。したがって、小道具を受け取っているコンポーネントの$keyを知る必要があります。
< div data-component =" Counter " data-key =" aUniqueKey " >
...
</ div >テンプレート言語でこれをループしているとしましょう。キーが一意であることを確認する必要があります。
# for (let i=0; i < 10 ; i++){
< div data-component =" Counter " key =" `aUniqueKey${i}` " > ... </ div >
}この属性を使用しない場合、各コンポーネントインスタンスに一意のキーが自動的に割り当てられます。 this.$key
data-props親コンポーネントからの状態を子供コンポーネントのpropsとして共有できます。マークアップは次のようになります
< div data-component =" Counter " key =" parentCounter " >
< div
data-props =" myAwesomeProp<-parentCounter:ofFive "
data-component =" DisplayAnything "
> </ div >
</ div >矢印の左側<-は、 DisplayAnythingコンポーネントの小道具の名前です。矢印の右側は、親コンポーネントの$key 、コロン:継承するstateの名前です。
その後、Lifecycle Methodを使用してpropsWillUpdateとpropsDidUpdate使用して、子供のコンポーネント内で変更を加えることができます。
Componentクラスを拡張しますか?カウンターを続けましょう。コンポーネントを作成するために必要な最小JSは次のとおりです。
class Counter extends Component {
constructor ( conf ) {
super ( conf ) ;
}
} super 、コンポーネントが必要とするベースメソッドとプロパティを追加します。
状態を直接変異させないでください。 this.setStateを呼び出します
setState ( stateObject , callbackFunction ) ;これは、ReactのSetStateと概念に似ていますが、異なる方法で実装されています。
デフォルトの状態をJSコンポーネントに追加して、DOMでオーバーライドできます
export default class Counter extends Component {
constructor ( conf ) {
super ( conf ) ;
this . state = {
count : parseInt ( this . state . count ) || 0 ,
isEven : this . state . count
? this . state . count % 2 === 0
? true
: false
: true ,
stateFieldFromDOM : this . state . stateFieldFromDOM || "default cat" ,
stateFieldDefault : "default iPhone 11"
} ;
this . setState ( this . state ) ;
} <div data-component="Counter" data-state="{"count": 4, "isEven":true, "stateFieldFromDOM": "some value here"}"
上記の状態フィールドは、デフォルトのJS状態フィールドをオーバーライドします。
setStateからの値のバインディングは、常にtextContentになります。 State/Propsを使用してHTMLをレンダリングする場合は、その値にWatcherを追加し、新しいHTMLを収容する$refsノードを更新できます。
watch ( ) {
return {
count : {
post ( newCount ) {
this . $refs . exclaimCount . innerHTML = `<div class="uppercase"> ${ newcount } !</div>` ;
}
}
}
}以下は、ライフサイクルのさまざまなポイントでコンポーネントにアクセスするために使用できる方法です
| ライフサイクル方法 | コンテクスト | 説明 |
|---|---|---|
| 接続 | コンポーネント/指数 | ライブラリがコンポーネント/指数のいずれかをワイヤする前に、他の方法にアクセスできるようになります |
| 接続 | コンポーネント/指数 | コンポーネント/指数が配線され、すべてのEventlistenersが配置された後 |
| 切断 | コンポーネント/指数 | EventListenersを削除し、メモリからコンポーネント/指数を削除する前に |
| Propswillupdate | コンポーネント/指数 | プロップがコンポーネント内で更新される前に、DOM変異は発生していません |
| propsdidupdate | コンポーネント/指数 | 小道具が更新され、DOMが変更された後 |
| StateWillUpdate | 成分 | 現在のコンポーネントの状態またはその扶養家族の小道具の状態が変更されました |
| StatedIdupdate | 成分 | 継承された小道具を持つ子コンポーネントがDOMの操作を行っており、状態と小道具が変更されました |
ComponentとExponentクラスには、オブジェクトを返す必要があるwatch方法があります。ウォッチャーを使用すると、コンポーネントのライフキャイル中に特定のstateまたはprops価値の変化に接続できます。これにより、 stateWillUpdate 、 stateDidUpdate 、 propsWillUpdate 、またはpropsDidUpdateですべてを刻むのではなく、状態ロジックを分離できます。これは、 Vue.JSでウォッチャーを密接に模倣することを目的としています。注: stateとpropsフィールドに名前を付けないでください。これは悪い練習であり、ウォッチャーを壊します。
watch ( ) {
return {
myField : {
pre ( newValue , oldValue ) {
// my logic
} ,
post ( newValue ) {
// my logic
}
}
}
}コンポーネント$watchersオブジェクトで監視されている状態フィールドを表示できます。
Exponentクラスを拡張して、 propsのみのあるコンポーネントを作成します。これはComponentよりもわずかに軽量です。より迅速に配線して、より少ないメモリを占有します。
import { Exponent } from 'domponent'
class StatelessThing extends Exponent{
constructor(conf){
super(conf);
}
}
次に、次のようにアクセスできます。
propsWillUpdatepropsDidUpdateなぜExponent ?
なぜなら、それが与えられたデータを単に解釈または説明するからです...そしてそれはコンポーネントのように聞こえます。
コンポーネントまたは指数には、次のフィールドが与えられます。
| フィールド名 | タイプ | アクセス | コンテクスト | 説明 |
|---|---|---|---|---|
| $ APP | 物体 | 公共 | コンポーネント/指数 | ドンポーネントアプリケーション全体 |
| $ b | 配列 | プライベート | コンポーネント/指数 | 内部使用のためのEventListenerバインディング |
| $ d | 物体 | プライベート | 成分 | 親コンポーネントはその子供に言及しています |
| $キー | 弦 | 公共 | コンポーネント/指数 | コンポーネントインスタンスの一意の識別子 |
| $ name | 弦 | 公共 | コンポーネント/指数 | コンポーネントタイプの名前 |
| $ p | 物体 | プライベート | コンポーネント/指数 | 小道具とそのDOM参照の内部コレクション |
| 小道具 | 物体 | 公共 | コンポーネント/指数 | 渡されたデータのキー/値ペア |
| $ root | 要素 | 公共 | コンポーネント/指数 | コンポーネントのルートドムノード |
| $ s | 物体 | プライベート | 成分 | 状態とそのDOM参照の内部コレクション |
| 州 | 物体 | 公共 | 成分 | 更新できるデータのキー/値ペア |
| $ウォッチャー | 物体 | 公共 | 成分 | 保存された変更関数とそれぞれの状態とプロップキー |
Init機能?この関数はアプリを作成し、すべてのコンポーネントを登録します。これは、必要な引数としてconfigオブジェクトを取得します。
const config = {
selector : document . getElementById ( "root" ) ,
components : { Counter } ,
appCreated : callbackFunction
} ;
const App = new Init ( config ) ;次に、次の方法を公開します。
と次のオブジェクト:
構成のcomponentsオブジェクトを除外し、最初からコンポーネントなしでアプリを作成することもできます。
createComponent@Params:
App . createComponent ( document . getElementById ( "added-html" ) , callback ) ; register@params
App . register ( NewComponent , callback ) ; deleteComponent@Params:
data-keyを介して割り当てたり、 this.$key App . deleteComponent ( "my-component-instance-key" , callback ) ; unregister@Params:
App . unregister ( "NewComponent" , callback ) ; data-属性を回避するには、他のセレクター、ライブラリなどと衝突する属性を回避するために、APP Configオブジェクトのデフォルト属性名をオーバーライドできます。
Init ( {
selector : getElementById ( 'root),
components : { Counter } ,
dataAttributes : {
component : 'mynamespace-component' ,
state : 'cool-state' ,
}
} ) ;これは、あなたのHTMLが次のようになることを意味します:
< div data-mynamespace-component =" Counter " data-cool-state =' {"count":12} ' >
...
</ div >オプションで、HTMLで使用する構文をカスタマイズできます。次のアイテムをカスタマイズできます。
INHERITS_FROM: '<-',
FROM_COMPONENT: '.',
KEY_VALUE: ':',
MULTIPLE_VALUES: "|",
METHOD_CALL: "->",
LIST: ","
これは、構成に追加できることを意味します。
{
customSyntax : {
LIST : "!" ,
METHOD_CALL : "#"
}
}そして、あなたのHTMLはこれを使用できます!
Domponentを使用して開発する場合、開発ビルドを使用すると、開発DOM(このguy->)からコンソールに役立つエラーとログが追加されますか?
これを使用する最も簡単な方法は、Webpackエイリアスを使用することです。
resolve : argv . mode === 'development' ? {
alias : {
domponent : 'domponent/dist/domponent.development.js'
}
} : { } ,このように、Webpackの開発ビルドは、DOMのヘルプでスプリンクされたバージョンのDOMponentの生産バージョンを交換します。
さまざまなテンプレートエンジンのコンポーネントHTMLを記述し、エンジンが「HTMLのチャンク」と呼ぶものとして、それらを部分的/フラグメントとして含めることができます。
Domponentを使用する方法の例をいくつか紹介します。
注:マークアップのこれらの構文の違いにもかかわらず、コンポーネントは単にJSクラス✌️であることを忘れないでください
パグ構文の例?
// counter.pug
mixin counter ( count )
div ( data - component = "Counter" data - state = `
{
"count": count,
"isEven": count % 2 === 0
}
` )
p ( data - bind = "state:Counter.count" ) # { count }
button ( data - action = "click->Counter.increment" ) + 1
button ( data - action = "click->Counter.decrement" ) - 1
// usage
+ counter ( 101119 )
+ counter ( 61316 )塊状の構文の例?
// counter.html
< div
data-component =" Counter "
th:fragment =" Counter "
th:data-state =' |{"count":${count}, "isEven": ${count % 2 == 0}}| '
>
< p data-bind =" state:Counter.count " th:text =" ${count} " > </ p >
< button data-action =" click->Counter.increment " >
+1
</ button >
< button data-action =" click->Counter.decrement " >
-1
</ button >
</ div >
// usage
< th:block th:replace =" ./counter.html :: Counter(count: 1289) " />
< th:block th:replace =" ./counter.html :: Counter(count: 491) " />かみそりの構文の例
Ruby on Rails構文の例?近日公開...
口ひげの構文の例?近日公開...
domponent [at] gmail [dot] com (サブジェクトDomponent Supportを使用してください。そうしないと、返信しません)@domponent