组件绑定将指定的组件注入到元素中,并且可选地将参数传递给它。

本节目录

  • 一个例子
  • 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>

组件生命周期

当组件绑定注入组件时,

  1. 请求您的组件加载器提供viewmodel工厂和模板

    • 可以查阅多个组件加载器,直到第一个识别组件名称并提供视图模型/模板。 此过程仅对每个组件类型发生一次,因为Knockout在内存中缓存生成的定义。

    • 默认组件加载器根据您注册的内容提供viewmodels /template。 如果适用,这是从AMD加载器请求任何指定的AMD模块的阶段。

    通常,这是一个异步过程。 它可能涉及对服务器的请求。 对于API一致性,Knockout默认确保加载过程作为异步回调完成,即使组件已经加载并缓存在内存中。 有关更多信息以及如何允许同步加载,请参阅上一节的控制同步/异步加载。

  2. 组件模板被克隆并注入到容器元素中

    任何现有内容都将被删除并丢弃。

  3. 如果组件有一个viewmodel,它被实例化

    如果viewmodel是作为构造函数给出的,这意味着Knockout调用新的YourViewModel(params)。

    如果viewmodel作为createViewModel工厂函数给出,Knockout callscreateViewModel(params,componentInfo),其中componentInfo.element是尚未绑定的未绑定模板的元素。

    这个阶段总是同步完成(构造函数和工厂函数不允许是异步的),因为每次组件被实例化时都会出现这种情况,如果涉及等待网络请求,性能将是不可接受的。

  4. viewmodel被绑定到视图

    如果组件没有viewmodel,则视图将绑定到您提供给组件绑定的任何参数。

  5. 组件处于活动状态

    现在组件正在运行,并且可以在需要时保持在屏幕上。

    如果传递给组件的任何参数是监控属性,则组件当然可以观察到任何改变,或者甚至回写修改的值。 这是它如何能够干净地与其父进行通信,而不是将组件代码紧密地耦合到使用它的任何父进程。

  6. 组件被拆卸,并且视图模型被删除

    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) 组件绑定的更多相关文章

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

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

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

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

  3. KnockoutJS 3.X API 第六章 组件(4) 自定义元素

    自定义元素提供了一种将组件注入视图的方便方法. 本节目录 介绍 例子 传递参数 父组件和子组件之间的通信 传递监控属性的表达式 将标记传递到组件中 控制自定义元素标记名称 注册自定义元素 备注1:将自 ...

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

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

  5. 第六章、forms组件

    目录 第六章.forms组件 一.注册功能手写 二.forms组件完整写法 基本使用 三.forms组件前端渲染标签组件 三.forms组件其他知识点 在python console测试 校验数据 f ...

  6. KnockoutJS 3.X API 第七章 其他技术(8) 异步错误处理

    注意:本文档适用于Knockout 3.4.0及更高版本. ko.onError Knockout包装内部异步调用,并在抛出原始错误之前查找可选的ko.onError回调以执行(如果遇到异常). 这使 ...

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

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

  8. KnockoutJS 3.X API 第四章 数据绑定(5) 控制流component绑定

    本节目录: 一个例子 API 备注1:仅模板式的component 备注2:component虚拟绑定 备注3:传递标记到component绑定 内存管理 一个例子 First instance, w ...

  9. KnockoutJS 3.X API 第七章 其他技术(7) 微任务

    注意:本文档适用于Knockout 3.4.0及更高版本. Knockout的微任务队列 Knockout的微任务队列支持调度任务尽可能快地运行,同时仍然是异步的,努力安排它们在发生I / O,回流或 ...

随机推荐

  1. @WebServlet用注解来实现servlet和url的映射

    package com.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.Se ...

  2. [BZOJ1997][HNOI2010] 平面图判定

    Description Input Output     是的..BZOJ样例都没给.     题解(from 出题人): 如果只考虑简单的平面图判定,这个问题是非常不好做的. 但是题目中有一个条件— ...

  3. TDD测试驱动开发

    TDD测试驱动开发 一.概念 TDD故名思意就是用测试的方法驱动开发,简单说就是先写测试代码,再写开发代码.传统的方式是先写代码,再测试,它的开发方式与之正好相反. TDD是极限编程的一个最重要的设计 ...

  4. 扩展BindingList,防止增加、删除项时自动更新界面而不出现“跨线程操作界面控件 corss thread operation”异常

    在做界面程序时,常常需要一些数据类,界面元素通过绑定等方式显示出数据,然而由于UI线程不是线程安全的,一般都需要通过Invoke等方式来调用界面控件.但对于数据绑定bindingList而言,没法响应 ...

  5. Android与H5交互

    1.初始化WebView控件 webView = (WebView) findViewById(R.id.webview); 2.设置WebView属性 WebSettings webSettings ...

  6. libCURL开源库在VS2010环境下编译安装,配置详解

    libCURL开源库在VS2010环境下编译安装,配置详解 转自:http://my.oschina.net/u/1420791/blog/198247 http://blog.csdn.net/su ...

  7. php随机ip

    $ip_long = array( array('607649792', '608174079'), //36.56.0.0-36.63.255.255 array('1038614528', '10 ...

  8. DirectX游戏编程(一):创建一个Direct3D程序

    一.环境 Visual Studio 2012,DirectX SDK (June 2010) 二.准备 1.环境变量(如没有配置请添加) 变量名:DXSDK_DIR 变量值:D:\Software\ ...

  9. Python之路第一课Day9--随堂笔记之一(堡垒机实例以及数据库操作)未完待续....

    一.堡垒机前戏 开发堡垒机之前,先来学习Python的paramiko模块,该模块机遇SSH用于连接远程服务器并执行相关操作 SSHClient 用于连接远程服务器并执行基本命令 基于用户名密码连接: ...

  10. git上传文件出错的时候

    $ git pull --rebase origin master 运行这个基本OK!