WeX5数据绑定:customBinding自定义绑定
优质
小牛编辑
134浏览
2023-12-01
自定义绑定(Custom Binding)允许我们通过代码实现自定义绑定规则,从而完成更高级的业务需求。
示例代码
//.js片段 justep.Bind.bindingHandlers.yourBindingName = { init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { // This will be called when the binding is first applied to an element // Set up any initial state, event handlers, etc. here }, update: function (element, valueAccessor, allBindings, viewModel, bindingContext) { // This will be called once when the binding is first applied to an element, // and again whenever any observables/computeds that are accessed change // Update the DOM element based on the supplied values here. };
在自定义绑定的方法中,我们需要向ko.bindingHandlers中添加一个绑定的名称,然后在里面实现init和update方法。从代码结构上来看,实现自定义绑定(custom Binding)并不复杂。下面我们来看一下init和update方法:
init:初始化方法,在DOM绑定时候被调用一次,并且只被调用一次。init方法有两个常用的场景
- 为DOM设置初始化状态
- 注册一些事件。例如我们需要在input改变的时候来同步数据到ko的ViewModel中,这个时候就需要在init的时候注册事件。
如果没有这些需要初始化一次的要求,那么init方法是不需要定义的(在init方法执行完成之后,ko会使用相同的参数调用update方法)。
update:update方法会在init方法执行完成之后执行,并且在监视属性或其他依赖属性(observables/computeds)发生改变的时候被调用来更新界面。update方法更常用一些。
下面是一个完整的例子:
//.W片段 <div bind-slideVisible="giftWrap" bind-slideDuration= "600">You have selected the option</div> <label><input type="checkbox" bind-checked="giftWrap" /> Gift wrap</label> //.js片段 justep.Bind.bindingHandlers.slideVisible = { update: function (element, valueAccessor, allBindings) { // First get the latest data that we're bound to var value = valueAccessor(); // Next, whether or not the supplied model property is observable, get its current value var valueUnwrapped = justep.Bind.unwrap(value); // Grab some more data from another binding property var duration = allBindings.get('slideDuration') || 400; // 400ms is default duration unless otherwise specified // Now manipulate the DOM element if (valueUnwrapped == true) $(element).slideDown(duration); // Make the element visible else $(element).slideUp(duration); // Make the element invisible } }; var Model = function(){ this.callParent(); this.giftWrap=justep.Bind.observable(true); };
如何支持虚拟节点?
ko的if、foreach等绑定支持虚拟节点,那么我们如何让自己的代码来支持虚拟节点呢?
首先,我们自定义一个绑定:
//.js片段 justep.Bind.bindingHandlers.randomOrder = { init: function (elem, valueAccessor) { // Pull out each of the child elements into an array var childElems = []; while (elem.firstChild) childElems.push(elem.removeChild(elem.firstChild)); // Put them back in a random order while (childElems.length) { var randomIndex = Math.floor(Math.random() * childElems.length), chosenChild = childElems.splice(randomIndex, 1); elem.appendChild(chosenChild[0]); } } };
在DOM节点中的用法
<div bind-randomOrder="true"> <div>First</div> <div>Second</div> <div>Third</div> </div>
如果我们想要在虚拟节点中使用,例如:
<!-- justep.Bind randomOrder: true --> <div>First</div> <div>Second</div> <div>Third</div> <!-- /justep.Bind-->
那么,我们需要在KO中注册,允许我们的自定义绑定用在虚拟节点中:
justep.Bind.virtualElements.allowedBindings.randomOrder = true;
接下来对我们的自定义绑定进行修改:
justep.Bind.bindingHandlers.randomOrder = { init: function (elem, valueAccessor) { // Build an array of child elements var child =justep.Bind.virtualElements.firstChild(elem), childElems = []; while (child) { childElems.push(child); child =justep.Bind.virtualElements.nextSibling(child); } // Remove them all, then put them back in a random order justep.Bind.virtualElements.emptyNode(elem); while (childElems.length) { var randomIndex = Math.floor(Math.random() * childElems.length), chosenChild = childElems.splice(randomIndex, 1); justep.Bind.virtualElements.prepend(elem, chosenChild[0]); } } };
这样一来我们自定义的绑定就能用在虚拟节点中了。