您不仅限于使用内置的绑定,如click,value绑定等,您可以创建自己的绑定。 这是如何控制视图模型如何与DOM元素进行交互,并且为您提供了大量的灵活性,以便于以复用的方式封装复杂的行为。

注册绑定

要注册绑定,请将其作为ko.bindingHandlers的子属性添加,比如如下例子:

ko.bindingHandlers.yourBindingName = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// 这是首次运行绑定的初始化回调函数
// 在此处设置初始状态和事件处理程序
    },
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// 当绑定首次应用到元素时,将调用一次
        // 每当监控属性/计算属性的值发生变化时
// 每当DOM绑定的元素值方法变化时被调用.
}
};

然后你可以使用它在任何数量的DOM元素:

<div data-bind="yourBindingName: someValue"> </div>

注意:你实际上不必提供完整的init和update回调 - 你可以只提供一个或另一个。

‘update’回调函数

当绑定应用于元素并跟踪您访问的任何依赖性(observables / computeds)时,Knockout将最初调用update回调。 当任何这些依赖关系改变时,将再次调用update回调。 将以下参数传递给它:

  • element — 此绑定中涉及的DOM元素

  • valueAccessor — 可以调用的JavaScript函数,以获取此绑定中涉及的当前模型属性。 调用此函数而不传递任何参数(即调用valueAccessor())以获取当前模型属性值。 要容易接受observable和plain值,请对返回的值调用ko.unwrap。
  • allBindings —可用于访问绑定到此DOM元素的所有模型值的JavaScript对象。 调用allBindings.get('name')检索名称绑定的值(如果绑定不存在则返回undefined); 或allBindings.has('name')来确定当前元素是否存在名称绑定。
  • viewModel — 此参数在Knockout 3.x中已弃用。 使用bindingContext。$ data或bindingContext $ raw用于访问视图模型的数据。
  • bindingContext — 保存可用于此元素的绑定的绑定上下文的对象。 此对象包括特殊属性,包括$ parent,$ parents和$ root,可用于访问与此上下文的祖先绑定的数据。

例如,您可能已经使用可见绑定控制元素的可见性,但现在您想要进一步进行和动画转换。 您希望元素根据observable的值滑入和滑出存在。 你可以通过编写调用jQuery的slideUp / slideDown函数的自定义绑定来实现:

You have selected the option

Gift wrap

源码:

<div data-bind="slideVisible: giftWrap, slideDuration:600">You have selected the option</div>
<label><input type="checkbox" data-bind="checked: giftWrap" /> Gift wrap</label> <script type="text/javascript">
var viewModel = {
giftWrap: ko.observable(true)
};
ko.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 = ko.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
}
};
ko.applyBindings(viewModel);
</script>

当然,乍一看很多的代码,但一旦你创建了你的自定义绑定,他们可以很容易地重用在许多地方。

‘init’回调函数

Knockout将为您使用绑定的每个DOM元素调用一次init函数。 init有两个主要用途:

  • 为DOM元素设置初始状态

  • 注册任何事件处理程序,例如,当用户单击或修改DOM元素时,可以更改关联的可观察事件的状态

KO将传递给init的参数和update回调具有完全相同的参数集。

继续前面的示例,您可能希望使用slideVisible将元素设置为在页面第一次出现时立即可见或不可见(没有任何动画幻灯片),以便动画只在用户更改模型状态时运行。 你可以这样做:

You have selected the option

Gift wrap

源码:

ko.bindingHandlers.slideVisible = {
init: function(element, valueAccessor) {
var value = ko.unwrap(valueAccessor()); // Get the current value of the current property we're bound to
$(element).toggle(value); // jQuery will hide/show the element depending on whether "value" or true or false
},
update: function(element, valueAccessor, allBindings) {
// Leave as before
}
};

这意味着如果giftWrap被定义为初始状态为false(即,giftWrap:ko.observable(false)),则相关联的DIV最初将被隐藏,然后当用户稍后检查该框时滑入视图。

在DOM事件后修改observable

您已经了解如何使用udpate,以便在监控属性的更改时,可以更新关联的DOM元素。 但是在另一个方向的事件呢? 当用户对DOM元素执行某些操作时,您可能需要更新关联的监控属性。

您可以使用init回调作为注册事件处理程序的地方,这将对关联的observable进行更改。 例如

Name:

You're editing the name

Edit name

源码:

<p>Name: <input data-bind="hasFocus: editingName" /></p>

<!-- Showing that we can both read and write the focus state -->
<div data-bind="visible: editingName">You're editing the name</div>
<button data-bind="enable: !editingName(), click:function() { editingName(true) }">Edit name</button> <script type="text/javascript">
var viewModel = {
editingName: ko.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.unwrap(value))
element.focus();
else
element.blur();
}
};
ko.applyBindings(viewModel,document.getElementById('eq3'));
</script>

现在,您可以通过将元素绑定到可监控对象来读取和写入元素的“焦点”。

备注,虚拟绑定

如果您希望自定义绑定可用于Knockout虚拟元素语法,可使用如下写法:

<!-- ko mybinding: somedata --> ... <!-- /ko -->

KnockoutJS 3.X API 第五章 高级应用(1) 创建自定义绑定的更多相关文章

  1. KnockoutJS 3.X API 第五章 高级应用(3) 虚拟元素绑定

    注意:这是一种高级技术,通常仅在创建可重用绑定的库时使用. 这不是你通常需要做的时候使用Knockout构建应用程序. Knockout的控制流绑定(例如,if和foreach)不仅可以应用于常规DO ...

  2. KnockoutJS 3.X API 第五章 高级应用(2) 控制后代绑定

    注意:这是一种高级技术,通常仅在创建可重用绑定的库时使用. 默认情况下,绑定仅影响它们应用到的元素. 但是如果你想影响所有的后代元素呢? 为此,只需从绑定的init函数中返回{controlsDesc ...

  3. KnockoutJS 3.X API 第五章 高级应用(4) 自定义处理逻辑

    在典型的Knockout应用程序中,DOM元素是动态添加和删除的,例如使用模板绑定或通过控制流绑定(if,ifnot,with和foreach). 当创建自定义绑定时,通常需要添加清除逻辑,当Knoc ...

  4. KnockoutJS 3.X API 第五章 高级应用(5) 使用预处理扩展Knockout绑定语法

    注意:这是一种高级技术,通常仅在创建可重用绑定或扩展语法的库时使用. 这不是你通常需要做的时候使用Knockout构建应用程序. 从Knockout 3.0开始,开发人员可以通过提供在绑定过程中重写D ...

  5. KnockoutJS 3.X API 第六章 组件(1) 组件和自定义元素 - 概述

    Components (组件)是一个强大的,干净的方式组织您的UI代码,可重复使用的块. : -可以表示单独的控件/窗口小部件或应用程序的整个部分 -包含自己的视图,通常(但可选)自己的视图模型 -可 ...

  6. KnockoutJS 3.X API 第四章 数据绑定(1) 文本及样式绑定

    目录 本节将介绍六种文本绑定方式: visible绑定 text绑定 html绑定 css绑定 style绑定 attr绑定 可见文本绑定(visible) 使用visible绑定,来控制DOM元素的 ...

  7. Knockout应用开发指南 第五章:创建自定义绑定

    原文:Knockout应用开发指南 第五章:创建自定义绑定 创建自定义绑定 你可以创建自己的自定义绑定 – 没有必要非要使用内嵌的绑定(像click,value等).你可以你封装复杂的逻辑或行为,自定 ...

  8. KnockoutJS 3.X API 第四章(13) template绑定

    目的 template绑定(模板绑定)使用渲染模板的结果填充关联的DOM元素. 模板是一种简单方便的方式来构建复杂的UI结构 . 下面介绍两种使用模板绑定的方法: 本地模板是支持foreach,if, ...

  9. KnockoutJS 3.X API 第六章 组件(2) 组件注册

    要使Knockout能够加载和实例化组件,必须使用ko.components.register注册它们,从而提供如此处所述的配置. 注意:作为替代,可以实现一个自定义组件加载器(自定义加载器下一节介绍 ...

随机推荐

  1. 爬虫爬数据时,post数据乱码解决办法

    最近在写一个爬虫,目标网站是:http://zx.bjmemc.com.cn/,可能是为了防止被爬取数据,它给自身数据加了密.用谷歌自带的抓包工具也不能捕获到数据.于是下了Fiddler.     F ...

  2. c++ 时间类型详解 time_t

    Unix时间戳(Unix timestamp),或称Unix时间(Unix time).POSIX时间(POSIX time),是一种时间表示方式,定义为从格林威治时间1970年01月01日00时00 ...

  3. JavaScript 基础第六天

    一.引言 前面我们介绍了有关于内置对象的很多很多的API,讲道理得话如果想彻底的掌握那一定要经过一定的代码段沉淀下.大家可以想象一下,既然在程序中有很多的内置对象供我们使用,那我们是不是也可以定义一些 ...

  4. Android学习笔记之消息机制

    Android的消息机制主要是指Handler的运行机制以及Handler所附带的MessageQueue和Looper的工作过程.   1.为什么要使用Handler? Android规定访问UI只 ...

  5. 如何获得DataGrid中某行某列的对象

    假如某行是 Xm_struct x = this.Brow.SelectedItem as Xm_struct;则下面分别是第5和第七列的对象 TextBlock Ddjs = this.Brow.C ...

  6. java 动态代理示例,带主要注释

    Java proxy是基于反射,仅仅支持基于接口的动态代理. java 动态代理是一切架构的基础,必须了解. 废话少说,先上代码获得感性认识. 示例代码有主要注释. 接口: public interf ...

  7. MySql Windws 下自动备份脚本

    这几天正在做一个  使用MySQL数据库的项目,目前项目已经完成了,当部署好项目之后,正在考虑如何自动备份MySql数据库的问题,我在网上找了一下资料终于解决了,特此记录一下. @echo off e ...

  8. 【腾讯Bugly干货分享】安卓单元测试:What, Why and How

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d28349101cd07a5404c415 Dev Club 是一个交流移动 ...

  9. 【腾讯Bugly干货分享】深入源码探索 ReactNative 通信机制

    Bugly 技术干货系列内容主要涉及移动开发方向,是由 Bugly 邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. 本文从源码角度剖析 RNA 中 J ...

  10. Demystifying ASP.NET MVC 5 Error Pages and Error Logging

    出处:http://dusted.codes/demystifying-aspnet-mvc-5-error-pages-and-error-logging Error pages and error ...