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,回流或 ...
随机推荐
- 【MongoDB初识】-其他操作
又发现一种查询写法$wheredb.class.find({$}}) 排重db.class.distinct("stuCount") 一.MapReduce(摘录MongoDB实战 ...
- web 前端- 表格字段(文件大小)单位格式化算法
if (value === 0) return '0 B'; var k = 1024, // or 1000 sizes = ['B', 'KB', 'MB ...
- 添加ssh key
我现在根据<github入门和实践>来去摸索github 其实,我发现自己在看github时,感觉不适应,是因为自己太久没有碰到英文了.可以联想到以前当看到一个网页,根据汉字的标题或描述, ...
- js 逻辑或
逻辑或操作符由两个竖线来表示||,属于短路操作符,也就是说,如果第一个操作数的求职结果为true,就不会对第二个操作数进行求值 var found = true; var result = found ...
- Linux tricks
Environment Settings Path Globally set path is in /etc/profile; or the user's .bash_profile for part ...
- [BZOJ1106][POI2007] Tet 立方体大作战
Description 一个叫做立方体大作战的游戏风靡整个Byteotia.这个游戏的规则是相当复杂的,所以我们只介绍他的简单规则:给定玩家一个有2n个元素的栈,元素一个叠一个地放置.这些元素拥有n个 ...
- js 判断浏览器和ie版本号 收集
function testB () { // body... var isOpera = !!window.opera ||!!window.opr|| navigator.userAgent.ind ...
- 闭包和重写函数 返回IE浏览器版本号
开发过程中我们有时候需要知道IE的版本号,我们知道得到IE的版本号的方法: var v = 3, div = document.createElement('div'), all = div.getE ...
- PC端一些非经典兼容性问题小札
IE10默认在input框中输入内容后会显示一个‘X’按钮,方便删除输入的所有内容. 在password输入框显示一个眼睛的按钮,去掉叉叉和眼睛的方法如下: ::-ms-clear { display ...
- 关于PHP语言
------php语言与JavaScript的使用 方法是相似 <script type="text/javascript"> </script>--js与 ...