KOの反射

8723 ワード

最近やっと実際のプロジェクトでknockoutを使いました.js,MVVMモードの双方向バインドと通知機能は私を興奮させて、とても良い感じがして、この感じは当初原生のjsからjqueryに転向したように、それは新しい作成モードを開いて、もっと高いレベルからいくつかのフロントエンドの応用の需要を満たしました.jqueryもknockoutもnice的なもので、生産性の向上に良い促進作用があり、先端の完璧な組み合わせです.
jqueryはdocumetと対話する問題を重点的に解決し,knockoutはビジネスと対話する問題を重点的に解決した.
 
knockout.jsはドキュメントの面で詳しく書かれています.Live ExamplesTutorialもあります.すぐに上手になることができます.もう褒めざるを得ません.それは原生的に多くの机能を提供して、绝大な开発の需要を満たすことができて、ただ少し残念に思って、それはkoの初期化で、私の最初の方法は先にjsonを出力してkoに初期化して、それからkoをUIに更新させて、このように自身は问题がなくて、これも教科书の方法です.
 
しかし、いくつかのばらばらなデータをターゲットにすると煩雑になります.私の理想的な方法は、ばらばらなデータをUIに直接バインドし、UIデータをkoに反射させることです.これで完璧です.これには、UIがあるべき状態をタイムリーに表示できるというメリットがあります.jsonがkoを初期化することで、koが初期化されてUIが更新された瞬間の値の変化がいつも見られるので、コード潔癖な私には耐えられません.
 
koはカスタム拡張機能を提供して、アプリケーションを無限に広くして、私の考えも構想的に実現しました.それはreflect bindingをすることです.
ko.bindingHandlers.reflect = {

    init: function (element, valueAccessor, allValueAccessor, viewModel) {

        // observable value

        var observableValue = valueAccessor(), allAccessor = allValueAccessor();

        if (observableValue === false) { return; }

        // reflect select

        if (element.tagName === 'SELECT') {

            var optionsAccessor = allAccessor['options'],

                txtKey = allAccessor['optionsText'],

                valKey = allAccessor['optionsValue'],

                caption = allAccessor['optionsCaption'];

            var existingOptions = optionsAccessor();

            if (!existingOptions || !existingOptions.length) {

                var options = [];

                if (caption) {

                    var c = {};

                    c[txtKey] = caption;

                    c[valKey] = '';

                    options.push(c);

                }

                $(element).find('option').each(function () {

                    var item = {};

                    item[txtKey] = $(this).text();

                    item[valKey] = $(this).val();

                    options.push(item);

                });

                optionsAccessor(options);

            }

            observableValue($(element).val());

        }

        // reflect textarea

        if (element.tagName === 'TEXTAREA') {

            observableValue($(element).val());

        }

        // reflect input

        if (element.tagName === 'INPUT') {

            var t = element.type.toLowerCase();

            if (t === 'text' || t === 'hidden') {

                observableValue($(element).val());

            }

            if (t === 'radio' || t === 'checkbox') {

                var target = element;

                if (element.name) {

                    var find = $('input[name="' + element.name + '"]:checked');

                    if (find.length > 0) { target = find.get(0); }

                }

                var elval = $(target).val();

                if (target.checked && elval) {

                    observableValue(elval);

                } else {

                    observableValue(target.checked);

                }

            }

        }

    }

};
<select data-bind="reflect:Passenger, value:Passenger, options:PassengerOptions, optionsText:'tint', optionsValue:'vint'">

    <option value="1">1 person</option>

    <option value="2">2 persons</option>

    <option value="3">3 persons</option>

</select>
<input type="text" data-bind="reflect:Destination, value: Destination" value="XMN" />
function modelClass() {

    this.Passenger = ko.observable();

    this.PassengerOptions = ko.observableArray([]);

    this.Destination = ko.observable();

}

ko.applyBindings(new modelClass());

 
使用時にreflect bindingがdata-bindの1位にあることを確認するだけで、このreflect bindingは表の単一要素に対する反射バインドであり、この原理に従って任意のhtml要素上で自分の必要な値を反射することができる.