[knockout.js] 체크 상자를 비트 필드에 연결합니다

15010 단어 JavaScriptknockoutjs
작업 중에 비트 필드를 체크 상자에 직접 연결하고 싶은 장면이 있어서 했어요.
본가의 것을 모방하다checked 바인딩.
KnockoutJS bifField binding

하고 싶은 일


비트 필드(비트 마스크를 사용하여 플래그를 작성하는 값)의 각 플래그의 ON/OFF를 확인란에 대응
 0  1  0  1 ←2進数) ビットフィールド (10進数→ 4)
[ ][+][ ][+] ←チェックボックス
 0  0  0  1 ビットマスク(flag1)
 0  0  1  0  ビットマスク(flag2)
 0  1  0  0  ビットマスク(flag3)
...

사용법


checked 바인딩의 기본 용법과 대체로 같다.
View
<input type="checkbox" data-bind="bitField: bitFieldValue, checkedFlag: flag1"/>
<input type="checkbox" data-bind="bitField: bitFieldValue, checkedFlag: flag2"/>
<input type="checkbox" data-bind="bitField: bitFieldValue, checkedFlag: flag3"/>
値: <span data-bind="text: bitFieldValue"> </span>
ViewModel
ko.applyBindings({
    bitFieldValue: ko.observable(0),
    flag1: 1 << 0,  // = 0b0001
    flag2: 1 << 1,  // = 0b0010
    flag3: 1 << 2   // = 0b0100
});

복선상자 이외에 원웨이를 연결하는 방법


복선상자 이외의 곳에 귀속시키려면 ViewModel→View의 원웨이만 귀속할 수 있습니다.
특수한 방법이 아니라 비트 연산만 한다property & flag.
View
<!-- visible binding の例 -->
<span data-bind="visible: bitFieldValue() & flag1">
    flag1 が ON です
</span>

<!-- Twitter Bootstrap で checkbox の見た目をトグルボタンにする例 -->
<label class="btn" data-bind="css: { active: bitFieldValue() & flag1 }">
    <input type="checkbox" style="display: none;"
             data-bind="bitFIeld: bitFieldValue, checkedFlag: flag1"/>
    FLAG1
</label>

동작 샘플


KnockoutJS bitField binding : jsFiddle
Knockout ES5 플러그인을 사용하는 버전은 다음과 같습니다.
KnockoutJS bitField binding (ES5) : jsFiddle
요일의 비트 필드와 Linux의 파일 권한을 모델로 샘플을 만들었습니다.

사용자 정의 바인딩


다음 코드는 ko입니다.호출하기 전에 삽입하면 사용할 수 있습니다.
knockout.js 이외에 다른 의존 프로그램 라이브러리가 없습니다.
bitFIeld-binding
ko.bindingHandlers.bitField = {
    'after': ['value', 'attr'],
    'init': function (element, valueAccessor, allBindings) {
        var propWriters = allBindings()['_ko_property_writers'];

        function checkedFlag() {
            return allBindings['has']('checkedFlag')
                ? ko.unwrap(allBindings.get('checkedFlag'))
                : element.value;
        }

        function updateModel() {
            // This updates the model value from the view value
            // It runs in response to DOM events (click) and changes in checkedFlag.
            var isChecked = element.checked,
                elemValue = checkedFlag();

            // When we're first setting up this computed, don't change any model state.
            if (!shouldSet) {
                return;
            }

            var modelValue = valueAccessor();
            var unwrapped = ko.unwrap(modelValue);
            if (oldElemValue !== elemValue) {
                if (isChecked) {
                    if (oldElemValue !== undefined) {
                        unwrapped &= ~oldElemValue;
                    }
                    unwrapped |= elemValue;
                }
                oldElemValue = elemValue;
            } else {
                if (isChecked) {
                    unwrapped |= elemValue;
                } else {
                    unwrapped &= ~elemValue;
                }
            }
            if (ko.isObservable(modelValue)) {
                modelValue(unwrapped);
            } else if (propWriters['bitField']) {
                propWriters.bitField(unwrapped);
            } else {
                valueAccessor(unwrapped);
            }
        }

        function updateView() {
            // This updates the view value from the model value.
            // It runs in response to changes in the bound (checked) value.
            var modelValue = ko.unwrap(valueAccessor());

            element.checked = (modelValue & checkedFlag()) > 0;
        }

        if (element.type !== "checkbox") return;

        var oldElemValue = checkedFlag(),
            shouldSet = false;

        // Set up two computeds to update the binding:

        // The first responds to changes in the checkedFlag value and to element clicks
        ko.computed(updateModel, null, { disposeWhenNodeIsRemoved: element });
        ko.utils.registerEventHandler(element, "click", updateModel);

        // The second responds to changes in the model value (the one associated with the bitField binding)
        ko.computed(updateView, null, { disposeWhenNodeIdRemoved: element });

        shouldSet = true;
    }
};
ko.expressionRewriting._twoWayBindings['bitField'] = true;

좋은 웹페이지 즐겨찾기