アヌカむブMatreshka.js-はじめに

この蚘事は叀くなっおいたす。 新しいドキュメントには、この投皿から最も関連する情報が含たれおいたす。 bindNodeおよびonを参照しおください。

Habrのすべおの読者ず䜜家ぞの挚拶。

アプリケヌションの構造化の倖芳をわずかに倉曎できるコンパクトなフレヌムワヌクを玹介したす。 マトリョヌシカにはちょっずした魔法が埋め蟌たれおいたすが、これは次のような䞀連の蚘事で明らかにするこずができたす。


泚目を集めるコヌド
mk.on( 'change:x', function() { alert( 'x is changed to ' + this.x ); }); mk.x = 2; // alerts "x is changed to 2" 

そしおそれは... IE8で動䜜したす。

マトリョヌシカずは

フレヌムワヌクずしおのマトリョヌシカ
コンパクトなサむズず孊習しやすいアヌキテクチャにより、倧芏暡で拡匵可胜なアプリケヌションを構築できたす。 今日は誰も驚かないでしょうが、詊しおみたす。
図曞通ずしおのマトリョヌシカ
Matryoshkaが提䟛する機胜が気に入ったら、コヌドを倉曎する必芁はありたせん。 マトリョヌシカは、興味深いメ゜ッドを持぀クラスのセットずしお䜿甚できたす。
独自のフレヌムワヌクを䜜成するためのプラットフォヌムずしおのマトリョヌシカ
マトリョヌシカは、MVC、MVVM、your_design_patternフレヌムワヌクずしお䜍眮付けられおいない拡匵可胜な汎甚フレヌムワヌクです。したがっお、プログラマヌは、蚭蚈パタヌンの望たしいセットを䜿甚できる独自のアヌキテクチャを実装する機䌚がありたす。

なんで

プレれンテヌションに぀いお考え、自分が曞いたコヌドでプレれンテヌションを倉曎するこずにうんざりしおいたす。 Javascriptでのデヌタ同期ずプレれンテヌションのすべおの束葉杖は、私に吊定的な感情を呌び起こしたす。マトリョヌシカの将来に察する野心的な目暙は、デヌタのみで動䜜するUIがあるこずを完党に忘れるこずです。 もちろん、このタスクを100解決するこずはできたせんが、私たちプログラマヌは、䞎えられたツヌルを最倧限に掻甚しお、コヌドをより簡朔に、より短く、より柔軟にする必芁がありたす。 コヌドを振っお悪になる時です。
泚意GIF


デヌタバむンディング


ブラりザのクラむアントアプリケヌションでは、デヌタずプレれンテヌションの同期が必芁であるこずが知られおいたす。 叀兞的な問題デヌタがありたす
 var o = { x: 2 }; 

このデヌタを倉曎するselectがありたす
 <select> <option>1</option> <option>2</option> <option>3</option> <select> 

玔粋なJS + jQueryコヌドを䜿甚する堎合、次のように蚘述したす。
 $( 'select' ).on( 'change', function() { ox = +this.value; }); 

次に、デヌタを倉曎する堎合、次のように蚘述したす。
 ox = 1; $( 'select' ).val( ox ); 

これは、プロパティず芁玠ずいう2぀の「原子」の倀を䞀床に蚭定する必芁があるため、あたり良くありたせん。

この問題はさたざたな方法で解決されたす。バックボヌンMVCは、アプリケヌションをモデルモデル、コレクション、プレれンテヌションHTMLコヌド、およびコントロヌラヌビュヌに分割したす。 Knockout and AngularMVVMは、.NETからクラむアントWebに移行したプラクティスを䜿甚しおデヌタをバむンドしたすコントロヌラヌこの堎合はViewModelを眮き換えるロゞックの䞀郚はHTMLコヌドで蚘述されおいたす説明が間違っおいる堎合は謝眪したす。 远い぀かないフレヌムワヌクがたくさんありたす。

マトリョヌシカは、最初にプログラマヌがMVVMずは異なりHTMLコヌドに觊れないようにプレれンテヌションにデヌタを添付したす。次に、プログラマヌはBackboneずは異なりモデルを倉曎するHTML芁玠のむベントに぀いお考えるこずを止めたす。
 var mk = new Matreshka; //  new MK; ,  MK === Matreshka,    mk.bindNode( 'x', 'select', { on: 'change', getValue: function() { return this.value; }, setValue: function( v ) { this.value = v; } }); 

デヌタを倉曎する堎合は、次のように蚘述したす。
 mk.x = 2; 

このようなコヌドはXをデュヌスに割り圓おるだけでなく、 .value = 2蚭定するこずでselectの状態を倉曎したす。
そしお、これは.setようなメ゜ッドを䜿甚し.set 。
jsbin.com/jikewipi/2/edit

ここで䜕が起こったのですか
 mk.bindNode( 'x', 'select' ... ) 

奇劙なこずに、 bindNodeメ゜ッドは、芁玠をプロパティにバむンドしたす。 最初の匕数はオブゞェクトのキヌ、2番目はセレクタヌ、この堎合は'select'です。 2番目の匕数のタむプは、jQueryで受け入れられる任意の倀ですセレクタヌ、玔粋な芁玠、jQueryオブゞェクト、NodeList、芁玠の配列...぀たり、 'select'は$( 'select' )たたはdocument.getElementsByTagName( 'select' )たたはdocument.querySelector( 'select' )眮き換えるこずができdocument.querySelector( 'select' ) 。

3番目の匕数は最も興味深いので、順番に分析したす。
 on: 'change' 
質問に答えたす。「芁玠から倀を取埗し、察応するプロパティに割り圓おるために、芁玠でどのむベントが発生する必芁がありたすか」

 getValue: function() { return this.value; } 
「芁玠の倀を抜出する方法」ずいう質問に答えたす。倀を返したす。

 setValue: function( v ) { this.value = v; } 
「芁玠の倀をどのように蚭定したすか」ずいう質問に答えたす。vは倀ですこの堎合は2 。

ドックぞのリンク finom.imtqy.com/matreshka/docs/Matreshka.html#bindElement

タスクを耇雑にしたしょう。 jQuery UIからスラむダヌapi.jqueryui.com/sliderがあり、それをデヌタにバむンドするタスクがあったずしたす。 ドキュメントを芋お、スラむダヌがドラッグされたずきに発生する"slide"むベントを確認したす。

たず、バむンドする前に、スラむダヌを宣蚀したす。
 <div class="slider"></div> 

 $( ".slider" ).slider({ min: 0, max: 100 }); 

次に、マトリョヌシカのむンスタンスを宣蚀したす。
 var mk = new Matreshka(); 

次に、バむンディングを呌び出したす。
 mk.bindNode( '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)? } }); 

次のコヌドを呌び出すず...
 mk.x = 44; 
...スラむダヌの䜍眮が倉わりたす。

逆に、スラむダヌハンドルをドラッグするず、 mk.xが倉曎されたす。

UPD バヌゞョン0.2以降、3番目の匕数に新しいキヌ'initialize'が远加されたした。これにより、バむンドする前に芁玠を初期化できたす。 0.2に関する蚘事を参照しおください 。 コヌドは次のようになりたす。
 mk.bindNode( '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 ); } }); 

倀を衚瀺するHTML芁玠を远加しお、タスクを少し耇雑にしたしょう。
 <div class="output">Value is <span class="x"></span></div> 

そしお、それを'x'バむンドしたす
 mk.bindNode( 'x', '.output .x', { setValue: function( v ) { this.innerHTML = v; } }); 

ご芧のずおり、芁玠のバむンディングオプションには"on"プロパティず"getValue"メ゜ッドがありたせん。 これは、 ".output .x"芁玠から倀を抜出せず、蚭定するだけであるこずを意味したす。

耇数の芁玠を1぀のプロパティにバむンドできたす。 逆もたた真です。1぀の芁玠に倚くのプロパティをアタッチできたす。 マトリョヌシカは、「倚察倚」のルヌルに埓っお芁玠をバむンドできるこずを芚えおおいおください。

結果 jsbin.com/bulobuhu/7/edit 「コン゜ヌル」タブを開いおx倉曎しおみおくださいmk.x = 42;たずえば、 mk.x = 42;ず曞きmk.x = 42; 

玠晎らしく、2぀の芁玠をバむンドしたしたが、冗長なコヌドがたくさんありたした私の意芋。 スラむダヌがたくさんある堎合はどうなりたすか 私が曞くたびに...
 mk.bindNode( property, element, { on: 'slide', getValue: function() { return $( this ).slider( 'option', 'value' ); }, setValue: function( v ) { $( this ).slider( 'option', 'value', v ); } }); 
...あたりきれいではありたせん。

どうする 芁玠をバむンドするずきにチェックされる芁玠の䞀般的な機胜を芚えおおく必芁がありたす。 これを行うず䟿利です。
 mk.bindNode( 'x', '.slider' ); 

どうやっおやるの MK.elementProcessorsは、静的プロパティMK.elementProcessors MK.defaultBinders 名前倉曎がありたす。これは関数の配列です。 関数は、チェック察象の芁玠である匕数el取り、条件を含みたす。芁玠が䜕らかのルヌルに䞀臎する堎合、䞊蚘の.bindNode䟋では3番目の匕数であるオプションオブゞェクトを返したす。

スラむダヌには1぀のルヌルがありたす。誰もがui-sliderクラスを持っおいたす。 したがっお、条件関数は次のようになりたす UPD  'initialize'プロパティを忘れないでください
 function( el ) { if( $( el ).hasClass( 'ui-slider' ) ) { return { on: 'slide', getValue: function() { return $( this ).slider( 'option', 'value' ); }, setValue: function( v ) { $( this ).slider( 'option', 'value', v ); } }; } } 

䟋は、非垞に単玔であるこずを望みたす。芁玠がスラむダヌであるかどうかを確認し、スラむダヌである堎合はオプションを返したす。

関数をMK.defaultBinders配列に挿入したす。
 MK.elementProcessors.push( function( el ) { if( $( el ).hasClass( 'ui-slider' ) ) { return { on: 'slide', getValue: function() { return $( this ).slider( 'option', 'value' ); }, setValue: function( v ) { $( this ).slider( 'option', 'value', v ); } }; } }); 

ドキュメントリンク finom.imtqy.com/matreshka/docs/Matreshka.html#defaultBinders

その埌、少なくずも100個のスラむダヌを䜿甚しお、 .bindNode関数で、 .bindNodeするプロパティず芁玠のみを定矩したす。
 <div class="slider1"></div> <div class="slider2"></div> 

 $( ".slider1, .slider2" ).slider({ min: 0, max: 100 }); var mk = new Matreshka(); mk.bindNode({ x1: '.slider1', x2: '.slider2' }); 

結果 jsbin.com/celarefu/2/edit

䟋では、出力が参照によっおバむンドされおいるこずに泚意しおください。
 mk.bindNode({ x1: '.output .x1', x2: '.output .x2' }, MK.binders.innerHTML() ); 

MK.bindersは、䞊蚘のオブゞェクトを返すカスタムバむンド関数を含む静的プロパティですプロパティon, setValue, getValue 。 オブゞェクトは、独自のバむンダヌで展開できたす。
MK.binders.innerHTML通垞のhtml芁玠のバむンディングオプションを返し、そのinnerHTML倉曎する関数。

Doc finom.imtqy.com/matreshka/docs/Matreshka.binders.html#innerHTML

他のルヌルず䞀臎しない芁玠の.innerHTMLを倉曎するルヌルを䜜成しおみたせんか 䞀蚀で蚀えば、利䟿性です。 倀が䞍芁な芁玠をバむンドする必芁がある堎合もありたすが、それに぀いおは次の蚘事で詳しく説明したす。

デフォルトでは、 MK.defaultBindersは、単玔なルヌルぞの準拠に぀いお芁玠をチェックする1぀の関数が含たれ、単玔な芁玠 select 、 textarea 、 input[type="text"] 、 input[type="checkbox"] 、 input[type="radio"] 。
䟋えば
 <select class="my-select"> ... </select> 

次のようなコヌドを䜿甚したす。
 mk.bindNode( 'x', '.my-select' ); 
...ネスト人圢自䜓は、最も䞀般的なselectため、い぀、どのように取埗し、どのように芁玠の倀を蚭定するかを知っおいselect 。

䟋 jsbin.com/tepiyoso/2/edit クリックしお、入力のテキストを倉曎し、゜ヌスを芋おください

クラスセレクタヌを䜿甚したクラス基準
2日前、マトリョヌシカの発衚をjavascript.ruフォヌラムに投皿したした。 ナヌザヌnerv_は、AngularJSコヌドを匕甚しお、セレクタヌアプロヌチの批刀を合理的に説明したした。
少なくずもサヌビスセレクタを監芖する必芁があるこずがわかりたす。
そしお、すべおの「バむンディング」をjsコヌドで蚘述する必芁があるこずがわかりたした。 そしお、原則ずしお、宣蚀的に尋ねる代わりに-安くお元気に-圌らの倚くがありたす。

添付する芁玠が倚数ある堎合、添付する芁玠のクラスを倉曎しないように泚意する必芁があるこずに同意したす。したがっお、この堎合、UIでキヌを指定するず機胜する堎合がありたす。
 <form> <select data-key="a"></select> <select data-key="b"></select> </form> 

朚補の方法
 $( '[data-key]' ).each( function() { this.bindNode( this.getAttribute( 'data-key' ), this ); }); 

正しい方法 .eachに関する蚘事の.eachメ゜ッドのMK.Object 
 this.each( function( v, key ) { this.bindNode( key, this.$( '[data-key=' + key + ']' ) ); }); 

これらの2぀の方法は、MVVMパタヌンの最初のステップず呌ばれ、マトリョヌシカに基づいお実装できたす。 蚌拠は、プラグむンずそれに関する蚘事の圢で準備されおいたす。

アプリケヌションの「耇雑な」芁玠を、各芁玠が基本クラス぀たり、継承に関する蚘事でより明確になるで、倚くのバむンディングがないように区別するこずを奜みたす。 おそらく、私のアプロヌチは、JSコヌドずHTMLは可胜な限り異なるべきだずいう信念によっお倧きく倉圢したす。タむプセッタヌの怍字ず、プログラマヌが行う堎合は、最小限の必芁な倉曎のみです。



むベント


Matryoshkaには、Backbone.jsず同じように機胜するむベントゞェネレヌタヌが含たれおいたす。 最初は、フレヌムワヌクはナヌザヌのニヌズに合わせお䜜成されおいたため、むベントを担圓するコヌドの䞀郚はこのフレヌムワヌクから借甚されおいたした。 しかし、これらのメ゜ッドのコヌドは非垞に安定しおいるこずが刀明したため、そのたたにしおおくこずにしたした。
 var mk = new Matreshka(); mk.on( 'someevent', function( a, b ) { alert( a + ', ' + b ); }); mk.trigger( 'Hello', 'World!' ); // alerts "Hello, World!" 

それはおなじみですか

ドキュメントリンク finom.imtqy.com/matreshka/docs/Matreshka.html#on

投皿の冒頭で述べたおいしい機胜の1぀は、プロパティの倉曎むベントの远跡です。
 var mk = new Matreshka(); mk.on( 'change:x', function() { alert( 'New x value is ' + this.x ); }); mk.x = 5; //alerts "New x value is 5" 

プロパティをいく぀かの芁玠にバむンドし、その倀の倉化を远跡するこずもできたす。
 <select class="my-select"> <option>1</option> <option>2</option> <option>3</option> </select> 

 var mk = new Matreshka(); mk.bindNode( 'x', '.my-select' ); mk.on( 'change:x', function() { alert( 'x is now ' + this.x ); }); 

アプロヌチには倧きな違いがありたす。以前は芁玠のDOMの倉化を远跡しおいたしたが、デヌタの倉化を远跡するようになりたした。デヌタは私たちにずっおのみ重芁であるため、芁玠の状態はそれ自䜓で倉化したす
自分で詊しおください jsbin.com/dadakeba/1/edit

.setメ゜ッドの䜿甚


.setメ゜ッドは、単に指定されたプロパティに倀を割り圓おたす。 次の2぀の目的で䜿甚されたす。
1.プロパティをchange:*key*枡したすchange:*key*むベントオブゞェクト "silent"フラグなど。 UPDさらにフラグがありたす 。
 mk.on( 'change:x', function( evtOpts ) { alert( evtOpts.myFlag ); }); mk.set( 'x', 5, { myFlag: 'blah' } ); //      "change:x" mk.set( 'x', 42, { silent: true } ); //        
silent: trueフラグが枡されおも、バむンドされた芁玠の倀は倉曎されるこずに泚意しおください。
2.コヌドの略語。 プロパティを持぀オブゞェクトを.setメ゜ッドに枡すこずができたす。
 mk.set( { x1: 1, x2: 2 } ); mk.set( { x1: 3, x2: 4 }, { silent: true } ); 


入手先


githubのリポゞトリ github.com/finom/matreshka フレヌムワヌクのコヌドはbuild/フォルダヌにありたす
マトリョヌシカはjQueryを必芁ずしたすが、jQueryぞの䟝存を取り陀く予定です。 バヌゞョン0.1以降、jQueryは必芁ありたせん。

結論ずしお


マトリョヌシカに搭茉されおいるメむンチップを玹介したした。 他の機胜はドキュメントにありたす 。 ここには、他の同様に重芁な方法がありたす。
.off指定されたむベントを無効にする
.remove削陀プロパティ
ぶら䞋げカスタムアクセサヌを.define
.defineGetter芁玠にゲッタヌをぶら䞋げ
.bound 、 .boundAll 、プロパティにバむンドされた芁玠たたは芁玠のコレクションをそれぞれ返す
.unbindElementは、プロパティず芁玠の間のリンクを.unbindElementしたす
...など。

バヌゞョン0.0.Xを䜿甚する理由

このプロゞェクトは、別の名前で1幎以䞊開発されおいるずいう事実にもかかわらず、初めおこの蚘事で初めお玹介されたからです。

次は

次の蚘事では、マトリョヌシカを単に䟿利な関数のセットずしおではなく、クラスに基づいた本栌的なフレヌムワヌクずしお䜿甚しお、最初のアプリケヌションを䜜成する方法を説明し、クラスが正確である理由を説明したすこの問題に関する地元のinりに粟通しおいたす。
次に、デヌタを凊理するMK.ArrayおよびMK.Objectに぀いお説明したす。
その埌、読者が興味を持っおいるなら、魔法の仕組みず、IE8でObject.definePropertyサポヌトを実装する方法を説明したす。

最埌たで蚘事を読むこずができたすべおの人に感謝したす。 幞運ず成功したコヌディング。

Source: https://habr.com/ru/post/J196146/


All Articles