- はじめに
- 継承
- MK.Object
- MK.Array
- Matreshka.js v0.1
- Matreshka.js v0.2
- TodoMVCの実装
みなさんこんにちは。 Matreshka.jsフレームワークの次のバージョン0.2への更新を紹介します。 マトリョーシカは、オープンソースコードを備えた汎用フレームワークであり、そのイデオロギーは外観よりもデータの優位性です:インターフェースがデータと同期する方法のルールを設定し、インターフェースイベントがデータに関係しない場合を除き、データのみで動作します、ボタンをクリックするか、フォームを送信するだけでは、データは変更されませんが、関数が起動され、データが処理されます)
例
Matryoshkaを使用すると、データとプレゼンテーションのさらなる同期を心配することなく、データとプレゼンテーション要素(オブジェクトのプロパティや入力フィールドの値など)を関連付けることが非常に簡単になります。 たとえば、最も単純なバインディングは次のようになります。
インスタンスを作成します。
xプロパティを
要素に
。
データを変更する
プロパティxに異なる値を割り当てた後、それに応じて要素の状態が変化します。
ライブ例をご覧ください
入れ子人形のもう1つの重要な機能は、イベント(カスタムイベントを含む)です。 たとえば、マトリョーシカはプロパティの値の変化をキャッチできます。
コードは
を出力します。
これらおよびその他の機能の詳細については、上記のリンクを参照してください。
<select class="my-select"> <option>1</option> <option>2</option> <option>3</option> </select>
インスタンスを作成します。
var mk = new Matreshka();
xプロパティを
.my-select
要素に
.my-select
。
mk.bindElement( 'x', '.my-select' );
データを変更する
mk.x = 2;
プロパティxに異なる値を割り当てた後、それに応じて要素の状態が変化します。
ライブ例をご覧ください
入れ子人形のもう1つの重要な機能は、イベント(カスタムイベントを含む)です。 たとえば、マトリョーシカはプロパティの値の変化をキャッチできます。
mk.on( 'change:x', function( evt ) { alert( 'x ' + evt.value ); });
コードは
"x "
を出力します。
mk.x = '';
これらおよびその他の機能の詳細については、上記のリンクを参照してください。
マトリョーシカのウェブサイトへのリンク 。 githubリポジトリにリンクします 。
AMDサポート
Matryoshkaは、非同期モジュール定義仕様をサポートするようになりました。 言い換えれば、マトリョーシカはrequirejsのようなライブラリーと互換性があります。 これは、グローバル名前空間を損なうことなく、tru-codeを記述できるようになったことを意味します。 2つの接続タイプがサポートされています。名前付きモジュール要求と名前なしモジュール要求です。
名前付きモジュール:
requirejs.config({ paths: { xclass: 'path/to/matreshka', matreshka: 'path/to/matreshka' } }); require(['xclass', 'matreshka'], function(Class, MK) { return Class({ 'extends': MK //... }); });
しかし、これはむしろ新しいプロジェクトファイル構造を使用することの副作用です。 そして、推奨される方法は、名前のないモジュールをリクエストすることです:
require(['path/to/matreshka'], function( MK ) { return MK.Class({ 'extends': MK // ... }); });
ご覧のとおり、Matryoshkaには
Class
プロパティが含まれています。これは、クラスを作成する関数を複製します。追加のモジュールを要求する必要はありません。
Matreshkaメソッド#addDependency :新しい名前と追加機能
1.
addDependence
のプロンプトで
addDependence
メソッドの名前が
addDependency
に変更され
addDependency
た(彼に感謝します)。古いメソッドは「非推奨」とマークされています。
2.メソッドは、他のクラスのプロパティに依存関係を追加する約束された機能をサポートするようになりました。 2番目の引数の構文は次のとおりです。
[ , "", , "", , "" ... ]
-奇数要素を持つ配列-クラスのインスタンス、偶数-これらのインスタンスのキー。目的のプロパティが依存します。 例を見てみましょう:
this.addDependency( 'a', [ anotherInstance1, 'b', this, 'c', anotherInstance2, 'd' ], function( b, c, d ) { return b + c + d; });
ここで、プロパティ
"a"
"b"
は、
anotherInstance1
オブジェクトのプロパティ
"b"
、
anotherInstance1
オブジェクトのプロパティ
"d"
anotherInstance2
および独自のプロパティ
"c"
依存します。 古い構文は引き続き機能します。
this.addDependency( 'a', 'b c', function( b, c ) { return b + c; });
3.安全な中毒。 この点は構文に影響を与えません。このリリース以降、
addDependency
使用された場合、メソッドは無限ループを回避します。 プロパティ
"b"
がプロパティ
"b"
依存し、プロパティ
"b"
がプロパティ
"c"
依存し、プロパティ
"c"
が順番に
"b"
依存する状況を想像してください。 たとえば、抽象的な図:
this.addDependency( 'a', 'b', function( b ) { return b * 2; }); this.addDependency( 'b', 'c', function( c ) { return c * 3; }); this.addDependency( 'c', 'a', function( a ) { return a / 5; });
このコードの各依存関係により、次の原因が生じ、結果としてページがぶら下がります。 このようなエラーに対する保護が登場しました。コードは依存関係のチェーン全体に特別なフラグを渡し、フレームワークが潜在的に危険な依存関係に達するとチェーンが停止します。 新しいフォームの
addDependency
を使用すると、複雑な(またはそうではない)数式に基づいて相互依存関係を構築できます。これらの数式の実装にエラーが生じる心配はありません。 辺の長さで長方形の周囲を計算し、辺の長さを計算する例:
this.addDependency( 'p', 'a b', function( a, b ){ return (a + b) * 2; }); this.addDependency( 'a', 'p b', function( p, b ){ return p/2 - b; }); this.addDependency( 'b', 'p a', function( p, a ){ return p/2 - a; });
静的メソッドMatreshka.procrastinate
次の状況を想像してください(私の練習から取られます)。 チェックボックスなど、いくつかのテキストフィールドを持つフォームがあります。フォーム要素の1つの値が変更されると、アプリケーションはサーバーにリクエストを送信する必要があり、サーバーは3つのグラフをレンダリングするためのデータを返します。 グラフの描画はプロセッサにとって難しいタスクであり、弱いコンピューター( Highchartsなど) では0.5秒かかります。 退屈していて、チェックボックスを繰り返しクリックすることにしたユーザーを想像してください。 どうなるの? 多数のリクエストが送信され、多数の回答が返されます。これにより、グラフが何度も描画されます。 この場合、彼らは通常何をしますか? サーバー要求をキャンセルします。 問題は、落ち着くまで待つことができるのに、なぜこのリクエストが送信されたのかということです。 :)
この問題を解決するために、最も単純な関数(おそらく自転車)を使用しました。この関数は引数として別の関数を取り、その変更を返します。この関数は一定期間に1回しか実行できません。 それなしでは単一のプロジェクトではできないため、マトリョーシカコードに含めることが決定されました。 例:
var doSomethingHeavy = function( i ) { console.log( 'Ok', i ); }; var procrastinateSomethingHeavy = MK.procrastinate( doSomethingHeavy ); for( var i = 0; i < 100; i++ ) { procrastinateSomethingHeavy( i ); } // >> Ok 100
機能コード(マトリョーシカ以外で使用したい場合):
var procrastinate = function ( f, d, thisArg ) { var timeout; if( typeof d !== 'number' ) { thisArg = d; d = 0; } return function() { var args = arguments, _this = this; clearTimeout( timeout ); timeout = setTimeout( function() { f.apply( thisArg || _this, args ); }, d || 0 ); }; };
このメソッドは、「処理する」関数に加えて、遅延とコンテキストを引数として取ります。 遅延は、次に呼び出されたときに実際の関数呼び出しが何ミリ秒遅延するかを決定します。
そして、これは関数を決して呼び出さない場合の例です(理解を深めるため)。
var procrastinateSomethingHeavy = MK.procrastinate( function() { console.log( 'Ok' ); }, 1000 ); setInterval( function() { procrastinateSomethingHeavy(); }, 500 ); //
新しいバインドキーのinitialize
バインダーは、 Matreshka #bindElementメソッドの 3番目の引数です。 覚えている場合、これは3つのプロパティで構成されるオブジェクトです:
on
(プロパティを更新するDOMイベントによって)、
getValue
(要素からプロパティの値を抽出する方法)、
setValue
(プロパティの値を要素に設定する方法)。 詳細はこちらをご覧ください (ところで、マトリョーシカに関するすべての記事はリリースごとに更新され、関連資料です)。 現在、別のオプションのプロパティ
initialize
。
initialize
は、バインディング中、またはその前に開始する関数です。 関数のタスクはコードを甘くすることです。 最初の記事の例をご覧ください 。
まず、バインドする前に、スライダーを宣言します。
<div class="slider"></div>
$( ".slider" ).slider({ min: 0, max: 100 });
次に、マトリョーシカのインスタンスを宣言します。
var mk = new Matreshka();
次に、バインディングを呼び出します。
mk.bindElement( 'x', '.slider', { on: 'slide', // , getValue: function() { return $( this ).slider( 'option', 'value' ); // (. jQuery ui.slider)? }, setValue: function( v ) { $( this ).slider( 'option', 'value', v ); // (. jQuery ui.slider)? } });
コードはやや冗長です。
slider
クラスを使用して要素に2回アクセスします(最初にプラグインを使用してから、要素をバインドします)。 これは回避できます:
var mk = new Matreshka(); mk.bindElement( 'x', '.slider', { initialize: function() { $( this ).slider({ min: 0, max: 100 }); }, on: 'slide', getValue: function() { return $( this ).slider( 'option', 'value' ); }, setValue: function( v ) { $( this ).slider( 'option', 'value', v ); } });
Matreshka#defineSetterメソッド
ご想像のとおり、この新しいメソッドはプロパティのセッターを定義します。
this.defineSetter( 'x', function( value ) { return alert( value ); });
メソッドを使用する場合、組み込みのプロパティセッター(存在する場合)をグラインドし、プロパティ変更イベントが機能しないことを覚えておく必要があります。
this.x = 1; this.on( 'change:x', function( evt ) { // , - alert( 'x is changed to ' + evt.value ); }); this.defineSetter( 'x', function() { // ... }); this.x = 2;
イベント名の新しい構文:プロパティおよびコレクションアイテムのイベントハンドラーの追加
おそらく、このリリースで最も重要なことは、インスタンスの内部コンテンツにイベントハンドラーを追加する機能です。
イベント"@_"
プロパティ値がMatryoshkaのインスタンスである場合、 Matryoshkaから継承したクラス( MK.ObjectおよびMK.Arrayを含む)内にプロパティのハンドラーを追加できるようになりました。 例を見てみましょう:
var mk = new MK; mk.on( 'x@yeah', function() { alert( 'yeah' ); }); mk.x = new MK; mk.x.trigger( 'yeah' );
プロパティが定義される順序、およびハンドラーをアタッチするときは重要ではないことに注意してください。最初にイベントハンドラーを追加してから、プロパティを宣言できます。 さらに、プロパティの値が変更された場合、ハンドラーは新しい値に対してのみ機能し、古い値に対してはハンドラーが削除されます。
MK.Object
イベント"@_"
このイベント名を使用すると、
MK.Object
インスタンスのJSONキーのハンドラーを追加できます(JSONキーまたはデータを担当するキーについては、MK.Objectに関する記事を参照してください )。
var mkObject = new MK.Object; mkObject.on( '@yeah', function() { alert( 'yeah' ); }); mkObject.jset( 'x', new MK ); mkObject.x.trigger( 'yeah' );
プロパティが宣言される順序とイベントハンドラーも重要ではありません。
MK.Array
イベント"@_"
MK.Object
と同様に、
MK.Object
も同じ機会があります。この要素が
MK.Object
から
MK.Object
いる場合、ハンドラーは配列の任意の要素にハングアップします。
var mkArray = new MK.Array; mkArray.on( '@yeah', function() { alert( 'yeah' ); }); mkArray.push( new MK ); mkArray[ 0 ].trigger( 'yeah' );
これらの3つの変更は、
"yeah"
イベントをリッスンするだけでなく、
"change:"
などの他のイベントも安心してリッスンできます
"change:"
this.on( 'x@change:y', function() { /* ... */ } ); this.on( '@change:y', function() { /* ... */ } );
理論的には、この機能を使用すると、データツリーの深部にある他のイベントをリッスンすることで、凝ったイベント名を作成できます。 オブジェクトとして表現できるデータ構造があるとしましょう:
{ a: [{ b: { c: { e: 1 } } }, { b: { d: { e: 2 } } }] }
"e"
プロパティの変更の最後に到達するには、次のようなハンドラーを追加できます。
this.on( 'a@@b@@change:e', function() { /* ... */ } );
Matreshka#$ boundメソッド
マトリョーシカには、バインドされた要素を返す2つのメソッドがあります。最初のバインドされた要素または
null
を返すMatreshka#boundと 、バインドされた要素のコレクションを返すMatreshka#boundAllです。 これは、「コレクション」という用語を理解し、ドルを知ることに慣れている、 VanillaJSに精通していないjQueryを使用する初心者に問題を引き起こす可能性があります。 したがって、
$bound
メソッドがフレームワークに追加され、 Matreshka#boundAllとまったく同じことを行いました 。
this.bindElement( 'a', '#x, #y' ); this.$bound( 'a' ).animate( /* ... */ ); // jQuery
その他の変更
usejQueryとuseBalalaika
代わりにMatreshka.useAs $
バージョン0.1から、マトリョーシカはjQueryがページ上にない場合、Balaalaikaマイクロライブラリを使用してjQueryのハード依存関係を取り除きました。 この変更の結果は、jQueryの存在に関係なく、
usejQuery
メソッド(jQueryが
useBalalaika
後に接続された場合)と
useBalalaika
(jQueryが
useBalalaika
前に接続された場合)を使用して、
usejQuery
2つのライブラリのいずれかを使用する2つのメソッドの作成でしたただし、組み込みライブラリを引き続き使用する必要があります)。 今では、jQueryのようなライブラリを一般に使用できるメソッドが踊っています(
usejQuery
と
useBalalaika
は非推奨としてマークされています)。
使用例:
MK.useAs$( jQuery ); MK.useAs$( jQuery.noConflict() ); MK.useAs$( Zepto ); MK.useAs$( MK.$b ); //
この変更の結果、マトリョーシカは、ロードして、jQueryのみを使用する代わりに、ドル記号ライブラリが存在し、特定のメソッドがあればそれを使用します。 プロジェクトファイルのソースコードのどのメソッドを正確に見つけることができます 。
Xclass.sameメソッド
クラスにシタックスシュガーを追加する小さな変更( 継承に関する記事を参照)。 多くの場合、クラスを作成するとき、このクラスのコンストラクターは、独自のコンテキストで親のコンストラクターを呼び出すだけで済みます。
var MyClass = Class({ 'extends': AnotherClass, constructor: function() { AnotherClass.call( this, arguments ); }, someNewMethod: function() { /* ... */ } });
同じことがより簡潔にできるようになりました。
var MyClass = Class({ 'extends': AnotherClass, constructor: AnotherClass.same(), someNewMethod: function() { /* ... */ } });
要素がバインドされる前にDOMイベントハンドラー(たとえば、 "click::x"
)を追加する
Matryoshkaには、 Matreshka#onメソッドを使用して、添付された要素にイベントハンドラーを添付する機能があります。
this.bindElement( 'x', '.my-element' ); this.on( 'click::x', function() { alert( '.my-element is clicked' ); });
問題は、要素がバインドされる前にコレクションDOMハンドラーを追加できなかったことです。
bind
イベントを待って、このイベントが発生したときにハンドラーを追加することで、倒錯する必要がありました。
this.on( 'bind:x', function() { this.on( 'click::x', function() { alert( '.my-element is clicked' ); }); }); this.bindElement( 'x', '.my-element' );
これで、DOMイベントのバインド/追加の順序は重要ではなくなりました。
this.on( 'click::x', function() { alert( '.my-element is clicked' ); }); this.bindElement( 'x', '.my-element' );
バグ修正/リファクタリング
- Matreshka.Array#initializeSmartArray (操作中のメソッドのドキュメント)が
this
返すthis
- Matreshka.Array#createFromは引数として
undefined
を取ります - Matreshka.Arrayクラスに対して
"modify"
イベントが発生"modify"
ケースを変更しました -
Matreshka.Array
は同じ名前のイベントがありますが、別の場合に発生するため、プロパティが"remove"
ではなく削除されると、Matreshka.Array
が"delete"
イベントを発生させるようになりました -
[].forEach
が存在しない場合、 es5-shimを有効にするための提案とともにエラーが生成されます - バラライカパーサーのバグを修正
- Matreshka#一度のメソッドのバグが修正され、 Matreshka#offメソッドを使用してハンドラーを削除できるようになりました
- トライアド
eventName + eventHandler + context
は、インスタンスごとに1回のみ追加できるようになりました -
Class
関数のバグを修正(splice
vsslice
) - Matreshka#onおよびMatreshka#offメソッドのリファクタリング
- 小さなリファクタリングMatreshka#トリガーとMK#セット
次は?
1.次の記事では、TodoMVCの実装について紹介します。 記事の準備はできていますが、編集が必要です。 実装も準備ができていますが、ドキュメントは更新されています。
2.その後、
MK.Array
に関する大きな記事が計画され、以前の記事が置き換えられます。 そこで、メソッド、配列の要素がレンダリングされる方法、「モデル」、および配列メソッドにオプションを渡す方法について詳しく説明します。
3.既にテストされている多数の興味深い変更を含むバージョン0.3。 いつものように、記事があります。
その後、テキストのコーミングや英語に関連するエラーの修正など、ドキュメントの大規模なレビューが行われます。 メインページと「マトリョーシカを選ぶ理由」 ページのテキストは既に修正されています。
すべてに良い!