現代の世界では、javascriptに遭遇しない機会はほとんどありません。 Nodejsは私にとって最後のストローであり、RoRに失望しました(マジックとジェネレーターが多すぎます-ホリバー、ルビストはありません!)、私は再び狂気に屈しました:クライアントとサーバー上の1つの言語。 javascriptは言語としては美しいですが、MVVMまたは少なくとも私が気に入っているMVCを実装するフレームワークはありません。 それらはすべて重く、余分な(ジャンク)コードを書く必要があります。 したがって、MVVMのビジョンを訴え、キックのコミュニティから正しい方向に進みたいと思います。 最良の方向は、「ライブラリを見逃しました、%library_name%を見てください」ということです。なぜなら、表面のすべて(angularjs、knockoutjsなど)を見ていたからです。 さて、フレームワークは未加工であり、現在誰にも利益をもたらす可能性は低いため、待望のキックと引き換えに、それを書いたときに得た私の経験を簡単に定式化しようとします。
テスト中
彼はビルボにたくさんのハンカチ、彼のお気に入りのパイプとタバコを持ってきました。
まともなホビットがハンカチなしで旅行に行かないように、現代世界でテストせずに生きることは可能ですが、悲しいことです。 ブラウザーがjavascriptをわずかに異なる方法で認識することは誰にとっても秘密ではないと思います。
テストフレームワークとしてQUnitを選択しました。 私はjqueryが本当に好きで、jquery Foundationからのものであるという事実がスケールの最後の重みでした。 私は選択を後悔していませんが、認めなければなりません-非同期テストの最初の出会いは、その非自明な振る舞いにわずかな衝撃を与えましたが、ドキュメントを注意深く読んだ後、すべてが落ちました。
どんなに奇妙に聞こえるかもしれませんが、テストを開始するにはhtmlドキュメントが必要です。
私にはこんな感じ
<!DOCTYPE html> <html> <head> <title>Binding tests</title> <link rel="stylesheet" href="css/qunit.css" type="text/css" media="screen"> <script type="text/javascript" src="js/libs/require.js"></script> <script type="text/javascript" src="js/libs/qunit.js"></script> <script type="text/javascript" src="js/binding.js"></script> </head> <body> <h1 id="qunit-header">Tests</h1> <h2 id="qunit-banner"></h2> <div id="qunit-testrunner-toolbar"></div> <h2 id="qunit-userAgent"></h2> <ol id="qunit-tests"></ol> <div id="trash"></div> </body> </html>
リポジトリのクローンを作成するか、 こちらで動作を確認できます
テストを書くことは残っています。 私は、テストをモジュール、 モジュール方式にグループ化するというアイデアが本当に好きでした。 モジュールの名前としてファイル名を使用します-そして、これにより、落下部分をすばやく見つけることができます。
さて、テスト自体はテスト関数を使用して書かれています。 公式文書では、非常によく説明されています。
ここでも、例
test("Hash tests", function() { var obj = {}; ok(HashUtils.get(0) == HashUtils.get(0), "Equal objects, one hash (Number)"); ok(HashUtils.get(obj) == HashUtils.get(obj), "Equal objects, one hash (Object)"); ok(HashUtils.get({}) != HashUtils.get({}), "Different objects, different hashes"); });
QUnitには、プログラマの魂を温めるアメニティもあります。 特に、コンパイラが共著者になろうとするのではなく、コンパイラが同意しないロジックを修正するのではなく、その役割を素直に果たすことを確認したい場合は、自分で何かを設定することは常に良いことです。
QUnit.config.urlConfig.push({ id: "min", label: "Minified source", tooltip: "Load minified source files instead of the regular unminified ones." }); QUnit.config.autostart = false; ... require( tests.concat(document.location.href.indexOf("min=true") > 0 ? productionRequire : developmentRequire), function() { QUnit.start(); } );
ここでも説明全体がプロジェクトのWebサイトで利用できますが、クリックするのが面倒な人には:
qunitメニューにチェックボックスを追加し、有効になっている場合、URLにmin = trueが表示されます。
テストの自動開始をオフにすると、最終的に素晴らしいruquirejsライブラリが表示されます。そのライブラリの助けを借りて、コンパイルされたコードまたは開発者向けのコードをダウンロードします。
ここでは、ok、equal、またはdeepEqualメソッドの説明は行いません。完全でわかりやすい説明がここにある場合、これは不要です。 したがって、テストとqunitについては、おそらくすべてです。
コードのコンパイル
知りません サルマンは、大きな力だけが悪を抑えることができると信じていますが、他の何かが私に明らかにされました。 普通の人の世俗的なさまざまな行為が、闇を抑えるのに役立つことを実感しました。 普通の愛と優しさ。 ビルボバギンズを選ぶ理由 恐ろしいし、彼は私に勇気を与えてくれるからでしょう。
おそらく、現代世界での数キロバイトの戦いは少し奇妙に思えますが、私たちはサイトの読み込み時間を一瞬だけ増やすことで顧客数を10-20%減らす世界に住んでいます。そのため、特に難しくはないので、 。
コンパイラとして、 Google Closureを選択し、次のスクリプトを取得しました。
build.sh
rm -r -f出力
mkdir out
cat js /バインディング/ utils.js js /バインディング/ dom.js js /バインディング/ model.js js /バインディング/ events.js js /バインディング/ binding.js js /バインディング/ templates.js> out / binding.js
java -jar libs / compiler.jar --js out / binding.js --js_output_file out / binding-min.js --compilation_level SIMPLE_OPTIMIZATIONS
cat out / binding.js js / ui / button.js js / ui / input.js> out / binding-ui.js
java -jar libs / compiler.jar --js out / binding-ui.js --js_output_file out / binding-ui-min.js --compilation_level SIMPLE_OPTIMIZATIONS
mkdir out
cat js /バインディング/ utils.js js /バインディング/ dom.js js /バインディング/ model.js js /バインディング/ events.js js /バインディング/ binding.js js /バインディング/ templates.js> out / binding.js
java -jar libs / compiler.jar --js out / binding.js --js_output_file out / binding-min.js --compilation_level SIMPLE_OPTIMIZATIONS
cat out / binding.js js / ui / button.js js / ui / input.js> out / binding-ui.js
java -jar libs / compiler.jar --js out / binding-ui.js --js_output_file out / binding-ui-min.js --compilation_level SIMPLE_OPTIMIZATIONS
実際、ここには1行しかありません。つまり、
java -jar libs / compiler.jar --js out / binding.js --js_output_file out / binding-min.js --compilation_level SIMPLE_OPTIMIZATIONS
js-コンパイルされたファイルの名前
js_output_file-コンパイルされたコードを置くファイルの名前
compilation_level-コンパイルレベル
あなたにとって重要な何かを見逃した場合、より詳細な情報は、
java -jar compiler.jar --help
Binditjs
それがトーリンのスタイルでした。 彼は重要な人物でした。 彼が止められなかった場合、彼は完全に息切れするまで、同じ精神で終わりなく続きますが、彼は社会に新しいことを何も伝えませんでした。
トーリンの目を批判することはありません。もちろん、成功した確かに素晴らしい既存のフレームワークについてはコメントしません。 したがって、次の形式を提案します。理想的な(IMHO)フレームワークがデータバインディングにどのように見えるかについて空想します。
ここでさらに説明する内容をダウンロードします。
XOプロジェクトのすべての例を挙げます。 ここでプレイできます
本文には「私見」カードはありませんが、さらに読むと、あなたの宗教的または他の感情を傷つける可能性のある主観的な意見を書いていることを理解する必要があります。あなたが何かに同意しない場合、私は喜んであなたの推論されたコメントを読みますそして、私はそれに合理的に答えます。 私たちは皆大人です。
- モデルとビューのコードを投稿する必要があります( SRP )
- 記述したら、ビューコードは再利用しやすいはずです( DRY )
- 表現は、モデル層の形成の原則を指示するものではありません
- モデルからの同じデータは、追加のコードを記述することなく、ページ上で異なる表現を持つ場合があります
- モデルを変更すると、適切なプレゼンテーション方法が自動的にプルされるはずです
その結果、HTMLレイアウト、ビュー、モデルという三位一体が得られます。 コードを介してデータとプレゼンテーションをリンクすると、インターフェイスの宣言的表現がある場合、多少冗長になるようです。HTMLで許可されているため、レイアウトでプレゼンテーションとデータを示したいと思います。 その結果、次の構文が得られました。
<div class="pull-left" bind-data="board" bind-handler="BoardBinding"></div>
bind-dataはデータを取得する場所を示し、 bind-handlerはデータをユーザーに表示する方法を示します。 便利さについて少し考えた後、子供のコンテキストを示すbind-formも導入しました。 属性では、これはすべてです。ただし、バインドハンドラーを省略することができる場合を除き、バインドハンドラーはBinding.DefaultHandlersでタグの名前で検索されます。
var ButtonBinding = { init : function(binding) { binding.element.onclick = function() { binding.callBindingFunction(); } }, modelChanged : function(binding) { if (ObjectUtils.getObjectType(binding.getModel()) != ObjectUtils.TYPE_FUNCTION) { binding.element.setAttribute("disabled", "disabled"); return; } binding.element.removeAttribute("disabled"); } }; Binding.DefaultHandlers["BUTTON"] = ButtonBinding;
<button class="btn btn-success" bind-data="newGame">New game</button>
ButtonBindingを詳しく見てみましょう。モデルとビューが初期化されるときに呼び出されるinitと、モデルが変更されるときに呼び出されるmodelChangedの 2つのメソッドがあります。 これはこの例では使用されませんが、modelChangedには2つの追加引数があります。modelは変更されたオブジェクトであり、eventにはイベントの説明が含まれます。
接続は、オブジェクト自体のインスタンスでは構築されないことを説明する価値があります。
xoには$ data.Game.boardがあります-これは競技場の説明を含むオブジェクトです。 「New game」ボタンをクリックすると、 $ data.Gameのメソッドが呼び出されます
newGame : function() { this.board = new Board(DEFAULT_SIZE); this.state = { player : 0, winner : null }; }
この関数は新しいインスタンスを作成しますが、対応するビューのmodelChangedが呼び出され、イベントをトリガーしたオブジェクトとして$ data.Gameが渡され、イベントの説明がイベントに渡されることがわかります。
実際には、これは次のようなことを意味します。ビューは、bind-dataで指定されたデータで動作し、注目に値する幽霊のようなオブジェクト、つまりガベージコレクターでは動作しないことを確認できます。
現状とロードマップ
現在、それはプレプレプレアルファであり、すべてが変化する可能性があります。 この記事の目的は、あなたからの応答を取得することです。そのような構文はプロジェクトで便利かどうか、何が足りないのでしょうか? ライブラリはクロムでのみチェックされます。
ロードマップ
- 化粧品のリファクタリング(クラス名の整理-すべてをbinditに転送)
- 主要なブラウザーの安定化
- 追加のUIアセンブリ(メインタグ入力、ボタンなどのビュー)
- ...
- 利益
最後に、集合的な心にいくつかの質問をしたいと思います。
- UIをどのようにテストしますか? クリック、テキスト入力など、ユーザーの行動を模倣したライブラリは非常に便利です。
- ロードマップをロシア語に翻訳するには? ビューの代わりに「ビュー」から私を邪魔しますが、これは事実上の標準であり、ロードマップのロシアの類似物はさらに悪いです