注意:这是一种高级技术,通常仅在创建可重用绑定的库时使用。 这不是你通常需要做的时候使用Knockout构建应用程序。

Knockout的控制流绑定(例如,if和foreach)不仅可以应用于常规DOM元素,而且可以应用于由基于特殊注释的语法定义的“虚拟”DOM元素。 例如:

<ul>
<li class="heading">My heading</li>
<!-- ko foreach: items -->
<li data-bind="text: $data"></li>
<!-- /ko -->
</ul>

自定义绑定也可以与虚拟元素一起使用,但要启用此功能,必须通过使用ko.virtualElements.allowedBindings API明确告知Knockout您的绑定理解虚拟元素。

示例

为了开始,这里是一个自定义绑定,随机化DOM节点的顺序:

ko.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]);
}
}
};
<div data-bind="randomOrder: true">
<div>First</div>
<div>Second</div>
<div>Third</div>
</div>

但是,它不适用于虚拟元素。 如果您尝试以下操作:

<!-- ko randomOrder: true -->
<div>First</div>
<div>Second</div>
<div>Third</div>
<!-- /ko -->

...那么你会得到错误绑定的“randomOrder”不能与虚拟元素一起使用。 让我们解决这个问题。 要使randomOrder可用于虚拟元素,请先通知Knockout允许它。 添加以下内容:

ko.virtualElements.allowedBindings.randomOrder = true;

现在不会有错误。 但是,它仍然无法正常工作,因为我们的randomOrder绑定是使用不理解虚拟元素的普通DOM API调用(firstChild,appendChild等)编码的。 这就是为什么KO要求你明确选择加入虚拟元素支持的原因:除非你的自定义绑定是使用虚拟元素API编码的,否则它不会正常工作!

让我们更新randomOrder的代码,这次使用KO的虚拟元素API:

ko.bindingHandlers.randomOrder = {
init: function(elem, valueAccessor) {
// Build an array of child elements
var child = ko.virtualElements.firstChild(elem),
childElems = [];
while (child) {
childElems.push(child);
child = ko.virtualElements.nextSibling(child);
} // Remove them all, then put them back in a random order
ko.virtualElements.emptyNode(elem);
while(childElems.length) {
var randomIndex = Math.floor(Math.random() * childElems.length),
chosenChild = childElems.splice(randomIndex, 1);
ko.virtualElements.prepend(elem, chosenChild[0]);
}
}
};

请注意,我们现在使用的是ko.virtualElements.firstChild(domOrVirtualElement),而不是使用像domElement.firstChild之类的API。 randomOrder绑定现在将正确地使用虚拟元素,例如<! - ko randomOrder:true - > ... <! - / ko - >。

此外,randomOrder仍将使用常规DOM元素,因为所有ko.virtualElements API都与常规DOM元素向后兼容。

Virtual Element APIs(虚拟元素API)

Knockout提供了以下用于处理虚拟元素的功能。

  • ko.virtualElements.allowedBindings

    一个对象的键确定哪些绑定可与虚拟元素一起使用。 设置ko.virtual Elements.allowed Bindings.mySuper Binding = true以允许mySuperBinding与虚拟元素一起使用。

  • ko.virtualElements.emptyNode(containerElem)

    从真实或虚拟元素容器Elem中删除所有子节点(清除与其关联的任何数据,以避免内存泄漏)。

  • ko.virtualElements.firstChild(containerElem)

    返回实元素或虚拟元素容器元素的第一个子元素,如果没有子元素,则返回null。

  • ko.virtualElements.insertAfter(containerElem, nodeToInsert, insertAfter)

    插入节点插入作为实际或虚拟元素容器Elem的子元素,紧接在insertAfter之后的位置(其中insertAfter必须是containerElem的子元素)。

  • ko.virtualElements.nextSibling(node)

    返回在其真实或虚拟父元素中跟随节点的兄弟节点,如果没有下一个兄弟节点,则返回null。

  • ko.virtualElements.prepend(containerElem, nodeToPrepend)

    将nodePrepend插入为实元素或虚拟元素containerElem的第一个子元素。

  • ko.virtualElements.setDomNodeChildren(containerElem, arrayOfNodes)

    从真实或虚拟元素containerElem中删除所有子节点(在此过程中,清除与其关联的任何数据以避免内存泄漏),然后将所有节点fromarrayOfNodes作为其新子节点插入。

请注意,这并不意味着完全替代了一整套常规DOM API。 Knockout仅提供一组最小的虚拟元素API,以便在执行控制流绑定时执行所需的各种转换。

KnockoutJS 3.X API 第五章 高级应用(3) 虚拟元素绑定的更多相关文章

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

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

  2. KnockoutJS 3.X API 第五章 高级应用(1) 创建自定义绑定

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

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

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

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

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

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

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

  6. KnockoutJS 3.X API 第六章 组件(3) 组件绑定

    组件绑定将指定的组件注入到元素中,并且可选地将参数传递给它. 本节目录 一个例子 API 组件生命周期 备注1:仅限模板组件 备注2:使用没有容器元素的组件 备注3:将标记传递给组件 处置和内存管理 ...

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

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

  8. KnockoutJS 3.X API 第四章(14) 绑定语法细节

    data-bind绑定语法 Knockout的声明性绑定系统提供了一种简洁而强大的方法来将数据链接到UI. 绑定到简单的数据属性或使用单个绑定通常是容易和明显的. 对于更复杂的绑定,它有助于更好地了解 ...

  9. KnockoutJS 3.X API 第六章 组件(5) 高级应用组件加载器

    无论何时使用组件绑定或自定义元素注入组件,Knockout都将使用一个或多个组件装载器获取该组件的模板和视图模型. 组件加载器的任务是异步提供任何给定组件名称的模板/视图模型对. 本节目录 默认组件加 ...

随机推荐

  1. js的执行机制

    遇到一个问题,因为自己本身就是菜鸟的原因,弄懂了还是很高兴的. console.log(a) function a() { return "this is function" } ...

  2. 【九度OJ】题目1061:成绩排序

    题目描述: 有N个学生的数据,将学生数据按成绩高低排序,如果成绩相同则按姓名字符的字母序排序,如果姓名的字母序也相同则按照学生的年龄排序,并输出N个学生排序后的信息. 输入: 测试数据有多组,每组输入 ...

  3. 关于Xcode7中添加不了libresolv.dylib等类似库的问题

    Xcode7中,由于某些机制,使得我们在添加类似于 libresolv.dylib.libz.dylib等库的时候,直接在Build Phases中点击加号添加,似乎已经无法找到相应的库.此时,我们可 ...

  4. 关于合并“.a”文件时遇到的问题

    今天在给工程添加百度地图SDK时,涉及到百度地图的模拟器与真机环境下的.a文件的合并,在使用终端进行 合并时,出现: xcrun: error: active developer path (&quo ...

  5. 博客迁移至CSDN

    本人的技术博客已经迁移至CSDN,地址为http://blog.csdn.net/starrow,现为Lotus Domino开发领域最活跃丰富的博客,内容包括Lotus Domino, JavaSc ...

  6. 00.PHP学习建议

    各位师弟师妹,大家好~PHP不是我们专业的本该有的方向.我不知道大家为什么来学习这门语言,也许是自己了解之后喜欢这门语言(我想这种可能在我们专业是挺少的),也许是听守中哥说这门语言简单好学,为了躲避学 ...

  7. 使用Axure来仿真Vogue网站

    用户体验包括三部分:用户研究.视觉设计和交互设计.按顺序进行,在用户研究和视觉设计之后,开始交互设计,Axure是最好的交互设计的软件. Vogue是著名的奢侈品品牌,网站设计“高大上”,用Axure ...

  8. JavaScript中JSONObject和JSONArray相关知识备忘(网络转载)

    1.json的格式,有两种: {"key": "value"} //JSONObject(对象) [{"key1": "value ...

  9. 原生Ajax封装随笔

    XMLHttpRequest 对象用于和服务器交换数据.我们使用 XMLHttpRequest 对象的 open() 和 send() 方法: open(method,url,async) metho ...

  10. VS2012配置使用ICE通信接口

    1.下载安装Ice-3.5.1.msi http://www.zeroc.com/download.html 2.添加安装路径到环境变量path,D:\Program Files (x86)\Zero ...