除了内嵌的绑定,还可以创建一些自定义绑定,封装复杂的逻辑或行为。
注册绑定
添加子属性到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>