在ASP.NET MVC中使用Knockout實踐09,自定義繫結

Darren Ji發表於2014-11-04

Knockout真正強大之處在於繫結機制,通過data-bind屬性值體現繫結,不僅可以繫結值,還可以繫結事件,甚至可以自定義繫結。

 

從一個例子看Knockou的繫結機制

 

假設想給一個button元素變成jQuery UI的button,大致這樣做:

<button id="btn">點我</button>
$('#btn').button( icons: { primary: 'ui-icon-gear' } );

 

"他山之石,可以攻玉",實際上Knockout可以通過它的繫結機制來借用其它js類庫實現相同的功能。如果能做到以下這樣就好了:

<button data-bind="jqButton: { icons: { primary: 'ui-icon-gear' } }">點我</button>

 

如果我們想給Knockout增加自定義繫結,必須通過ko.bindingHandlers屬性。

<button data-bind="click: sayHello, jqButton: { icons: { primary: 'ui-icon-gear' } }">點我</button>


@section scripts
{
    <script src="~/Scripts/knockout-3.2.0.js"></script>
    <script type="text/javascript">
        ko.bindingHandlers.jqButton = {
            init: function (element, valueAccessor) {
                var options = valueAccessor() || {};
                $(element).button(options);
                ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
                    $(element).button("destroy");
                });
            }
        };
        var vm = {
            sayHello: function () {
                alert("hello");
            }
        };
        ko.applyBindings(vm);
    </script>
}

 

以上,通過ko.bindingHandlers,增加了一個名稱為jqButton的繫結。

1

 

到這裡,有必要了解一下Knockout的繫結機制了。

ko.bindingHandlers.myCustomBinding = {
    init: function(element, valueAccessor, allBindingsAccessor, data, context) {
      
    },
    update: function(element, valueAccessor, allBindingsAccessor, data, context) {
       
    }
}; 

 

init

函式只在元素第一次繫結的時候執行。通常用來給元素繫結一個handler。update函式只在View Model中,具有observable的成員值發生改變的時候被執行。

 

initupdate包含5個引數:

element表示實施繫結的DOM元素
valueAccessor 表示傳值給繫結機制的函式,該函式可能是View Model中具有Observable的成員,也有可能是json物件。
allBindingsAccessor 用來獲取運用在同一DOM元素上的所有繫結
data 用來獲取View Model
context繫結的上下文,包括$data, $parent, $parents, $root等屬性

 

更新View Model的時候讓DOM元素閃一下

 

繫結無非就是關乎View Model和Dom元素,現在,當View Model中具有Obserable的成員值反生變化的時候,讓DOM元素閃一下(實際上就是讓DOM元素先隱藏再慢慢顯現)。根據繫結機制,肯定要自定義update函式。

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<style type="text/css">
    .main {
        background-color: #CCC;
    }
</style>
<div class="main" data-bind="flash: name">
    <span data-bind="text: name"></span>
</div>
<hr/>
<input data-bind="value: name"/>
@section scripts
{
    <script src="~/Scripts/knockout-3.2.0.js"></script>
    <script type="text/javascript">
        ko.bindingHandlers.flash = {
            update: function(element, valueAccessor) {
                ko.utils.unwrapObservable(valueAccessor());
                $(element).hide().fadeIn(500);
            }
        };
        var vm = {
            name: ko.observable("darren")
        };
        ko.applyBindings(vm);
    </script>
}

2

每當input值發生變化,div區域總會閃一下。


 

給現有的繫結再套上一層繫結

 

比如說,Knockout已經有了一個名稱為text的繫結,當View Model中具有Obserable的成員值發生改變,繫結text的DOM元素值也會隨之發生變化。如果我們想讓text值發生變化的時候閃動一下,該如何做呢?

<input data-bind="value: name"/>
<hr/>
<span data-bind="fadeText: name"></span>
@section scripts
{
    <script src="~/Scripts/knockout-3.2.0.js"></script>
    <script type="text/javascript">
        ko.bindingHandlers.fadeText = {
            update: function(element, valueAccessor) {
                $(element).hide();
                ko.bindingHandlers.text.update(element, valueAccessor);
                $(element).fadeIn(500);
            }
        };
        var vm = {
            name: ko.observable("darren")
        };
        ko.applyBindings(vm);
    </script>
}

以上,當input值發生變化的時候,span的值隨之閃動並變化。

相關文章