KnockoutJS 3.X API 第六章 组件(3) 组件绑定
组件绑定将指定的组件注入到元素中,并且可选地将参数传递给它。
本节目录
- 一个例子
- API
- 组件生命周期
- 备注1:仅限模板组件
- 备注2:使用没有容器元素的组件
- 备注3:将标记传递给组件
- 处置和内存管理
一个例子
First instance, without parameters
Second instance, passing parameters
UI源码:
<h4>First instance, without parameters</h4>
<div data-bind='component: "message-editor"'></div> <h4>Second instance, passing parameters</h4>
<div data-bind='component: {
name: "message-editor",
params: { initialText: "Hello, world!" }
}'>
</div>
视图模型源码:
ko.components.register('message-editor', {
viewModel: function(params) {
this.text = ko.observable(params && params.initialText || '');
},
template: 'Message: <input data-bind="value: text" /> '
+ '(length: <span data-bind="text: text().length"></span>)'
});
ko.applyBindings();
注意:在更现实的情况下,通常从外部文件加载组件视图模型和模板,而不是将它们硬编码到注册中。
API
有两种方法使用组件绑定:
快速语法:
如果你只传递一个字符串,它被解释为一个组件名称。 然后注入命名的组件,而不向其提供任何参数。 例:
<div data-bind='component: "my-component"'></div>
也可以将监控属性作为组件名称。 在这种情况下,如果监控属性值更改,组件绑定将处理旧组件实例,并注入新引用的组件。 例:
<div data-bind='component: observableWhoseValueIsAComponentName'></div>
完整语法:
要向组件提供参数,请传递具有以下属性的对象:
name— 要注入的组件的名称。 同样,这可以是监控属性。params—将被传递给组件的对象。 通常,这是一个包含多个参数的键值对象,通常由组件的viewmodel构造函数接收。
例如:
<div data-bind='component: {
name: "shopping-cart",
params: { mode: "detailed-list", items: productsList }
}'>
</div>
组件生命周期
当组件绑定注入组件时,
请求您的组件加载器提供viewmodel工厂和模板
- 可以查阅多个组件加载器,直到第一个识别组件名称并提供视图模型/模板。 此过程仅对每个组件类型发生一次,因为Knockout在内存中缓存生成的定义。
- 默认组件加载器根据您注册的内容提供viewmodels /template。 如果适用,这是从AMD加载器请求任何指定的AMD模块的阶段。
通常,这是一个异步过程。 它可能涉及对服务器的请求。 对于API一致性,Knockout默认确保加载过程作为异步回调完成,即使组件已经加载并缓存在内存中。 有关更多信息以及如何允许同步加载,请参阅上一节的控制同步/异步加载。
组件模板被克隆并注入到容器元素中
任何现有内容都将被删除并丢弃。
如果组件有一个viewmodel,它被实例化
如果viewmodel是作为构造函数给出的,这意味着Knockout调用新的YourViewModel(params)。
如果viewmodel作为createViewModel工厂函数给出,Knockout callscreateViewModel(params,componentInfo),其中componentInfo.element是尚未绑定的未绑定模板的元素。
这个阶段总是同步完成(构造函数和工厂函数不允许是异步的),因为每次组件被实例化时都会出现这种情况,如果涉及等待网络请求,性能将是不可接受的。
viewmodel被绑定到视图
如果组件没有viewmodel,则视图将绑定到您提供给组件绑定的任何参数。
组件处于活动状态
现在组件正在运行,并且可以在需要时保持在屏幕上。
如果传递给组件的任何参数是监控属性,则组件当然可以观察到任何改变,或者甚至回写修改的值。 这是它如何能够干净地与其父进行通信,而不是将组件代码紧密地耦合到使用它的任何父进程。
组件被拆卸,并且视图模型被删除
If如果组件绑定的名称值可观察地改变,或者如果封闭的控制流绑定导致容器元素被移除,则在从DOM移除容器元素之前调用视图模型上的任何dispose函数。 参见本节:处置和内存管理。
注意:如果用户导航到完全不同的网页,浏览器会执行此操作,而不会要求页面中运行的任何代码进行清理。 所以在这种情况下不会调用dispose函数。 这是正常的,因为浏览器会自动释放所有使用的对象使用的内存。
备注1:仅限模板组件
组件通常有viewmodels,但它们不一定必须。 组件只能指定一个模板。
在这种情况下,组件视图所绑定的对象是您传递给组件绑定的params对象。 例:
ko.components.register('special-offer', {
template: '<div class="offer-box" data-bind="text: productName"></div>'
});
...可以注入参数:
<div data-bind='component: {
name: "special-offer-callout",
params: { productName: someProduct.name }
}'></div>
或者,更方便地,作为自定义元素:
<special-offer params='productName: someProduct.name'></special-offer>
备注2:使用没有容器元素的组件
有时,您可能想要将一个组件注入到视图中,而不使用额外的容器元素。 您可以使用基于注释标签的无容器控制流语法。 例如,
<!-- ko component: "message-editor" -->
<!-- /ko -->
...或传递参数:
<!-- ko component: {
name: "message-editor",
params: { initialText: "Hello, world!", otherParam: 123 }
} -->
<!-- /ko -->
<!-- ko -- >和<!-- / ko -- >注释作为开始/结束标记,定义一个包含标记的“虚拟元素”。 Knockout理解这个虚拟元素的语法,并绑定,就像你有一个真正的容器元素。
备注3:将标记传递给组件
您附加组件绑定的元素可能包含进一步的标记。 例如,
<div data-bind="component: { name: 'my-special-list', params: { items: someArrayOfPeople } }">
<!-- Look, here's some arbitrary markup. By default it gets stripped out
and is replaced by the component output. -->
The person <em data-bind="text: name"></em>
is <em data-bind="text: age"></em> years old.
</div>
虽然此元素中的DOM节点将被删除,并且不会默认绑定,但它们不会丢失。 相反,它们被提供给组件(在这种情况下,my-special-list),它可以将它们包括在它希望的输出中。
如果要构建表示“容器”UI元素的组件(如网格,列表,对话框或标签集),这需要注入并将任意标记绑定到公共结构中,这将非常有用。 它也可以在没有自定义元素的情况下使用上面显示的语法。
处置和内存管理
您的viewmodel类可能具有dispose函数。 如果实现了,当组件被删除并从DOM中删除时,Knockout会调用它(例如,因为相应的项从foreach中删除,或者如果绑定变为false)。
您必须使用dispose释放任何本质上不可回收的资源。 例如:
setInterval回调将继续触发,直到显式清除。- 使用clearInterval(handle)来停止它们,否则你的viewmodel可能被保存在内存中。
- ko.computed属性继续从其依赖关系接收通知,直到明确处置。
- 如果一个依赖是一个外部对象,那么一定要使用.dispose()在computed属性,否则它(可能还有你的viewmodel)将被保存在内存中。 或者,考虑使用pureComputed以避免手工处置的需要。
- 监控属性订阅将继续运行,直到明确被处理。
- 如果你订阅了一个外部的observable,一定要使用.dispose()在订阅,否则回调(可能还有你的viewmodel)将被保存在内存中。
- 外部DOM元素上手动创建的事件处理程序(如果在createViewModelfunction中创建)(甚至在常规组件视图模型内部,尽管适合您不应该使用的MVVM模式)必须删除。
- 当然,您不必担心在视图中释放由标准Knockout绑定创建的任何事件处理程序,因为KO会在删除元素时自动注销它们。
例如:
var someExternalObservable = ko.observable(123);
function SomeComponentViewModel() {
this.myComputed = ko.computed(function() {
return someExternalObservable() + 1;
}, this);
this.myPureComputed = ko.pureComputed(function() {
return someExternalObservable() + 2;
}, this);
this.mySubscription = someExternalObservable.subscribe(function(val) {
console.log('The external observable changed to ' + val);
}, this);
this.myIntervalHandle = window.setInterval(function() {
console.log('Another second passed, and the component is still alive.');
}, 1000);
}
SomeComponentViewModel.prototype.dispose = function() {
this.myComputed.dispose();
this.mySubscription.dispose();
window.clearInterval(this.myIntervalHandle);
// this.myPureComputed doesn't need to be manually disposed.
}
ko.components.register('your-component-name', {
viewModel: SomeComponentViewModel,
template: 'some template'
});
不必严格地需要仅仅依赖于相同viewmodel对象的属性来处理计算和订阅,因为这仅创建了JavaScript垃圾收集器知道如何释放的循环引用。 然而,为了避免不必记住哪些事情需要处理,你可能更喜欢在任何可能的地方使用pureComputed,并且显式地处置所有其他计算/订阅,无论技术上是否必要。
KnockoutJS 3.X API 第六章 组件(3) 组件绑定的更多相关文章
- KnockoutJS 3.X API 第六章 组件(5) 高级应用组件加载器
无论何时使用组件绑定或自定义元素注入组件,Knockout都将使用一个或多个组件装载器获取该组件的模板和视图模型. 组件加载器的任务是异步提供任何给定组件名称的模板/视图模型对. 本节目录 默认组件加 ...
- KnockoutJS 3.X API 第六章 组件(2) 组件注册
要使Knockout能够加载和实例化组件,必须使用ko.components.register注册它们,从而提供如此处所述的配置. 注意:作为替代,可以实现一个自定义组件加载器(自定义加载器下一节介绍 ...
- KnockoutJS 3.X API 第六章 组件(4) 自定义元素
自定义元素提供了一种将组件注入视图的方便方法. 本节目录 介绍 例子 传递参数 父组件和子组件之间的通信 传递监控属性的表达式 将标记传递到组件中 控制自定义元素标记名称 注册自定义元素 备注1:将自 ...
- KnockoutJS 3.X API 第六章 组件(1) 组件和自定义元素 - 概述
Components (组件)是一个强大的,干净的方式组织您的UI代码,可重复使用的块. : -可以表示单独的控件/窗口小部件或应用程序的整个部分 -包含自己的视图,通常(但可选)自己的视图模型 -可 ...
- 第六章、forms组件
目录 第六章.forms组件 一.注册功能手写 二.forms组件完整写法 基本使用 三.forms组件前端渲染标签组件 三.forms组件其他知识点 在python console测试 校验数据 f ...
- KnockoutJS 3.X API 第七章 其他技术(8) 异步错误处理
注意:本文档适用于Knockout 3.4.0及更高版本. ko.onError Knockout包装内部异步调用,并在抛出原始错误之前查找可选的ko.onError回调以执行(如果遇到异常). 这使 ...
- KnockoutJS 3.X API 第五章 高级应用(5) 使用预处理扩展Knockout绑定语法
注意:这是一种高级技术,通常仅在创建可重用绑定或扩展语法的库时使用. 这不是你通常需要做的时候使用Knockout构建应用程序. 从Knockout 3.0开始,开发人员可以通过提供在绑定过程中重写D ...
- KnockoutJS 3.X API 第四章 数据绑定(5) 控制流component绑定
本节目录: 一个例子 API 备注1:仅模板式的component 备注2:component虚拟绑定 备注3:传递标记到component绑定 内存管理 一个例子 First instance, w ...
- KnockoutJS 3.X API 第七章 其他技术(7) 微任务
注意:本文档适用于Knockout 3.4.0及更高版本. Knockout的微任务队列 Knockout的微任务队列支持调度任务尽可能快地运行,同时仍然是异步的,努力安排它们在发生I / O,回流或 ...
随机推荐
- React虚拟DOM浅析
在Web开发中,需要将数据的变化实时反映到UI上,这时就需要对DOM进行操作,但是复杂或频繁的DOM操作通常是性能瓶颈产生的原因,为此,React引入了虚拟DOM(Virtual DOM)的机制. 什 ...
- android 5.0以上通知栏、状态栏图标变成白色
在5.0以上的系统上发现,平常的自定义notification出来的icon,居然在状态栏上变成了纯白色的icon. 看源代码会发现: protected void applyColorsAndBac ...
- FTD团队目录
一.Daily Scrum Meeting[Alpha] · [Alpha]Daily Scrum Meeting 第一次 · [Alpha]Daily Scrum Meeting 第二次 · [Al ...
- 通过NFS(nfsroot)启动linux系统
Mounting the root filesystem via NFS (nfsroot) 英文原文位于inux内核源代码中的"Documentation/filesystems/nfs/ ...
- easyui-conbotree树形下拉框。。。转
最近一直在研究这个树形的下拉选择框,感觉非常的有用,现在整理下来供大家使用: 首先数据库的表架构设计和三级菜单联动的表结构是一样,(父子关系) 1.下面我们用hibernate建一下对应的额实体类: ...
- 【hihoCoder】1036 Trie图
题目:http://hihocoder.com/problemset/problem/1036 给一个词典dict,词典中包含了一些单词words.要求判断给定的一个文本串text中是否包含这个字典中 ...
- 日常工作bug总结
1.在使用jQuery的text()与val()使用时,如果按钮是<button></button>的形式使用text()写入时,在IE8下会出现延迟,即我在写定时器5秒倒计时 ...
- 单例模式和angular的services的使用方法
在现实生活中存在着有这样的特点的一些类: A.这些类只能有一个实例: B.这些能够自动实例化: C.这个类对整个系统可见,即必须向整个系统提供这个实例. 不妨举一个具体的单例模式的例子:比如教室里面的 ...
- Tomcat 配置续
为了便于tomcat升级 不用频繁重新修改相关配置文件 不用重新部署原有项目 新建目录将tomcat安装目录中的conf,log,webapp,work文件夹复制到里面,然后将系统变量里的CATALI ...
- java并发编程(十九)障碍器CyclicBarrier
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17512983 CyclicBarrier(又叫障碍器)同样是Java 5中加入的新特性,使 ...