除了内嵌的绑定,还可以创建一些自定义绑定,封装复杂的逻辑或行为。
注册绑定
添加子属性到ko.bindingHandlers来注册绑定:
ko.bindingHandlers.yourBindingName = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
// 第一次应用于元素时调用,在这里设置任何初始状态,事件处理程序等
}, update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
// 当绑定首先应用于元素时,将被调用一次,并且每当相关联的observable更改值时,都会被调用一次。并根据这里提供的值更新DOM元素。
}
};
然后在DOM元素上调用:
<div data-bind="yourBindingName: someValue"> </div>
init和update这两个函数不是必须都定义,也可以只定义其中一个。
当管理的observable改变的时候,KO会调用回调函数,传递一下参数:
♦ element:使用这个绑定的DOM元素
♦ valueAccessor:JavaScript函数,通过valueAccessor()可以得到应用到这个绑定的model上的当前属性值。
♦ allBindingsAccessor:JavaScript函数,通过allBindingsAccessor ()得到这个元素上所有model的属性值。
♦ viewModel :传递给ko.applyBindings使用的 view model参数,如果是模板内部的话,那这个参数就是传递给该模板的数据。
init回调
Knockout在DOM元素使用自定义绑定的时候会调用init函数。init的用途:
♦ 为DOM元素设置初始值
♦ 注册事件handle,例如当用户点击或者编辑DOM元素的时候,可以改变相关的的observable值的状态。
可以在页面第一次显示的时候设置该元素的状态(但是不使用任何动画效果),而只是让动画在以后改变的时候再执行。
ko.bindingHandlers.hideControl= {
init: function(element, valueAccessor, allBindingsAccessor,viewModel) {
var flag = localStorage.flag;
// 获取本地存储中的flag值
if(flag == 1){
$(element).hide();
}
},
update: function(element, valueAccessor, allBindingsAccessor,viewModel) {
}
};
update回调
通过visible绑定来控制一个元素的可见性,但是想让该元素在隐藏或者显示的时候加入动画效果。可以自定义自己的绑定来调用jQuery的slideUp/slideDown函数
ko.bindingHandlers.slideVisible = {
update: function(element, valueAccessor, allBindingsAccessor) {
// 首先获取最新的绑定值
var value = valueAccessor(), allBindings = allBindingsAccessor(); // 不管所提供的模型属性是否可观察到,获取其当前值
var valueUnwrapped = ko.utils.unwrapObservable(value); // 从另一个绑定属性中获取更多数据,除非另有说明,否则默认为400ms
var duration = allBindings.slideDuration || 400; // 操作DOM元素
if (valueUnwrapped == true)
$(element).slideDown(duration);
else
$(element).slideUp(duration);
}
};
其他形式的事件
知道了如何使用update回调,当obeservable值改变的时候,可以更新相关的DOM元素,对于其他形式的事件(如用户点击某个element的事件)想要更新相关的observable值。
可以使用init回调来注册一个事件handle,这样可以改变相关的observable值。
ko.bindingHandlers.hasFocus = { init: function (element, valueAccessor) {
$(element).focus(function () {
var value = valueAccessor();
value(true);
}); $(element).blur(function () {
var value = valueAccessor();
value(false);
});
}, update: function (element, valueAccessor) {
var value = valueAccessor();
if (ko.utils.unwrapObservable(value))
element.focus();
else
element.blur();
}
};
在DOM上调用
<p>Name: <input data-bind="hasFocus: editingName"/></p>
<div data-bind="visible: editingName">You're editing the name</div>
<button data-bind="enable: !editingName(), click:function() { editingName(true) }">Edit name</button>
绑定viewModel
<script type="text/javascript">
var viewModel = {
editingName: ko.observable()
};
ko.applyBindings(viewModel);
</script>