KnockoutJS - component 绑定

此绑定用于将组件插入 DOM 元素并选择性地传递参数。此绑定可以通过以下两种方式实现 −

  • 简写语法
  • 完整语法

简写语法

在此方法中,仅指定组件名称,而不指定任何参数。

语法

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

传递的参数值可以是可观察的。因此,每当可观察对象发生变化时,旧的组件实例将被释放,并根据刷新的参数值创建新的组件实例。

完整语法

此方法以对象的形式接受参数。

语法

<div data-bind = 'component: {
   name: "component-name",
   params: { param1: value1, param2:value2 ...}
}'></div>

该对象由以下两项组成 −

  • name − 这是要插入的组件的名称。如前所述,这可以是可观察对象。

  • params - 这是要传递给组件的对象。大多数情况下,这将是一个包含多个参数的键值对象。这大多数时候都是由 ViewModel 的构造函数接收的。

组件处理工作流程

下图解释了通过组件绑定注入组件时发生的过程。

component lifecycle

让我们详细看看这个过程 −

从组件加载器接收 ViewModel 工厂和模板 − 默认加载器请求并接收已注册的 ViewModel 和模板。默认情况下,这是一个异步过程。

克隆组件模板 − 在此步骤中,将克隆组件模板并将其插入 DOM 元素。现有内容(如果有)将被删除。

实例化 ViewModel(如果有) −在此步骤中,ViewModel 被实例化。如果 ViewModel 以构造函数的形式提供,则 KO 会调用。

new ViewModelName(params)

如果 ViewModel 以工厂函数的形式提供,即 createViewModel,则 KO 会调用。

createViewModel(params, yourcomponentInfo)

此处 yourcomponentInfo.element 是插入模板的元素。

将 ViewModel 绑定到视图 − 在此阶段,ViewModel 绑定到视图。如果未提供 ViewModel,则使用组件绑定中提到的参数进行绑定。

现在组件已准备就绪 − 在此阶段,组件已准备就绪并处于运行状态。组件会密切关注可观察的参数(如果有),以便写入更改的值。

如果组件丢失,则处置 ViewModel − 如果组件绑定名称值发生可观察的变化,或者某些控制流绑定删除了 DOM 元素容器本身(用于保存组件输出),则调用 ViewModel 的处置函数。处置发生在任何元素容器从 DOM 中删除之前。

示例

让我们看看下面的示例,它演示了组件绑定的使用。

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Component binding</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
   </head>
   
   <body>
      <h4>Component binding without parameters</h4>
      <div data-bind = 'component: "calculate-sum"'></div>

      <h4>Component binding passing parameters</h4>
      <div data-bind = 'component: {
         name: "calculate-sum",
         params: { number1: 2, number2: 3 }
      }'></div>

      <script>
         ko.components.register('calculate-sum', {
            
            viewModel: function(params) {
               this.number1 = ko.observable(params && params.number1);
               this.number2 = ko.observable(params && params.number2);

               this.result = ko.computed(function() {
                  var sum = Number(this.number1()) + Number(this.number2());
                  if ( isNaN(sum) )
                  sum = 0;
                  return sum;
               },this);
            },
            
            template: 'Enter Number One: <input data-bind = "value: number1" /> <br> <br>'+
               ' Enter Number Two: <input data-bind = "value: number2" /> <br> <br>'+
               ' Sum  = <span data-bind = "text: result" />'
         });

         ko.applyBindings();
      </script>
      
   </body>
</html>

输出

让我们执行以下步骤来查看上述代码的工作原理 −

  • 将上述代码保存在 component-bind.htm 文件中。

  • 在浏览器中打开此 HTML 文件。

  • 在两个文本框中输入数字,并观察总和是否计算出来。

观察

仅模板组件

无需 ViewModel 即可创建组件。该组件可以仅包含如下所示的模板。

ko.components.register('my-component', {
    template: '<div data-bind = "text: productName"></div>'
});

DOM 将如下所示 −

<div data-bind = 'component: {
   name: "my-component",
   params: { productName: someProduct.name }
}'></div>

使用没有 DOM 容器元素的组件绑定

可能存在无法将组件插入 DOM 元素的情况。基本绑定仍可借助无容器语法执行,具体操作请参见以下注释标记。

<!--ko--> 和 <!--/ko--> 用作开始和结束标记,使其成为虚拟语法,并将数据绑定为真实容器。

内存管理和处置

处置函数可作为 ViewModel 的一部分进行选择添加。如果包含此函数,则每当组件丢失或容器元素本身被移除时,都会调用此函数。使用处置函数释放不需要的对象占用的资源是一种很好的做法,默认情况下这些资源不可进行垃圾回收。以下是几个示例 −

  • setInterval 方法将持续运行,直到明确清除。clearInterval (handle) 用于停止此过程。

  • ko.computed 属性需要明确处置。否则,它们可能仍会继续从其底层可观察对象接收通知。使用纯计算函数可以避免手动处置。

  • 确保在订阅上使用 dispose() 方法,否则它会持续触发更改,直到处置为止。

  • 在 DOM 元素上创建并在 createViewModel 内创建的自定义事件处理程序需要处置。

knockoutjs_declarative_bindings.html