25 November 2015

组件绑定 component

component 组件绑定把一个特定功能的组件注入到绑定元素中去,还可以向组件中传递参数。

组件绑定的示例

视图层代码

<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

有两种方式来使用 component 组件绑定。

1 快捷方式

传递一个组件的名称,那么这个组件就被注入到元素中去了。 例如:

<div data-bind='component: "my-component"'></div>

快捷方式的值也可以是一个观察者。这个例子中,如果绑定组件发生变化,它会处理旧组件,然后注入新的变化之后的组件。例如

<div data-bind='component: observableWhoseValueIsAComponentName'></div>

2 完整方式

用下面的属性可以把参数传递到组件中。

  • name – 需要引入的组件的名称。再次说明,它是可以被观察的。
  • params — 传递到组件中的参数对象。key-value的方式可以传递多个值对象;参数是被组件视图模型的构造函数接受的。

例子

<div data-bind='component: {
    name: "shopping-cart",
    params: { mode: "detailed-list", items: productsList }
}'></div>

组件的生命周期

当一个组件绑定注入了一个组件

  • 1.视图模型的工厂函数和模板需要组件的加载

  • 2.组件模板被备份并注入到绑定的元素中

  • 3.如果组件有视图模型,那么它会被实例化

  • 4.视图模型会被绑定到视图上

  • 5.组件是活动的

  • 6.组件被关闭,它的视图模型被处理

注意1: 只有模板的组件

组件通常都有视图模型,但它们不是必须有的。一个组件可以只有模板。

这种情况下,传递的参数会直接传递到模板中进行使用。例如:

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>

…更简单的用法 ,可以看 自定义元素.

注意2:不带包含元素使用组件绑定

<!-- ko component: "message-editor" -->
<!-- /ko -->

和其他虚拟元素绑定一样的用法。

注意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节点会被剥离,默认并不会绑定,但是这些DOM不会消失。他们会被组件引用(例子中的my-special-list),组件的输出中会包含他们。

它的使用场景:组件表现出绑定元素内的UI元素。比如:表格、列表、对话框或者tab set ,这些都需要注入和绑定任意标签到一个公共的结构中。

dispose 内存管理

你的视图模型类中可能含有一个dispose函数。如果有的话,只要组件被关闭并从DOM中移除(比如相应的组件被从foreach中移除或者if的绑定之变成了false),KO就会调用这个dispose函数。

必须使用 dispose 来释放任何没有被垃圾回收器资源。例如:

  • setInterval 的回调函数在显示清除之前是一直存在于内存中的。

    要使用 clearInterval(handle) 来清除回调函数,否则视图模型会一直驻留在内存中。

  • ko.computed 属性在显示释放前,会一直从它的依赖那里接收通知。

    如果依赖是一个外部对象,ko.computed 属性需要调用 .dispose() ,否则它(也可能是视图模型对象)会一直驻留在内存中。

  • 在显示释放之前,对于观察者的订阅会一直存在。

    如果对一个外部对象订阅,那么订阅者需要调用 .dispose() ,否则订阅者的回调函数(也可能是视图模型对象)会一直驻留在内存中。

  • createViewModel 函数在外部DOM元素上手动创建的事件句柄需要移除。

    当然我们不需要关心释放任何事件以标准KO绑定创建的句柄,当元素被移除时,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'
});