目录

KnockoutJS - 快速指南

KnockoutJS - Overview

KnockoutJS基本上是一个用JavaScript编写的库,基于MVVM模式,可以帮助开发人员构建丰富的响应式网站。 该模型将应用程序的模型(存储数据),视图(UI)和视图模型(模型的JavaScript表示)分开。

KnockoutJS是由Microsoft员工Steve Sanderson于2010年7月5日开发并维护为开源项目.KO是用于KnockoutJS的缩写。 KO支持所有主流浏览器 - IE 6 +,Firefox 3.5 +,Chrome,Opera,Safari(桌面/移动)。

KnockoutJS的特点

以下列出了KnockoutJS的一些最突出的功能 -

  • Declarative Binding - HTML DOM元素使用非常简单的语法通过data-bind属性连接到模型。 使用此功能可以轻松实现响应。

  • Automatic UI Refresh - 对查看模型数据所做的任何更改都会自动反映在UI中,反之亦然。 无需编写额外的代码。

  • Dependency Tracking - KO属性与KO库函数/组件之间的关系是透明的。 自动跟踪KO属性中的数据更改并更新相应的受影响区域。

  • Templating - 模板是构建复杂UI结构的简单方便的方法 - 可以重复或嵌套块 - 作为视图模型数据的函数。

  • Extensible - 非常容易扩展自定义行为。

为什么要使用KnockoutJS?

  • KnockoutJS库提供了一种简单而干净的方式来处理复杂的数据驱动接口。 可以为Javascript对象创建自我更新的UI。

  • 它是纯JavaScript库,适用于任何Web框架。 它不是JQuery的替代品,但可以作为提供智能功能的补充。

  • KnockoutJS库文件非常小巧轻便。

  • KnockoutJS独立于任何其他框架。 它与其他客户端或服务器端技术兼容。

  • 所有KnockoutJS中最重要的是开源,因此可以免费使用。

  • KnockoutJS已完整记录。 官方网站提供完整的文档,包括API文档,实时示例和交互式教程。

KnockoutJS - Environment Setup

使用KnockoutJS非常容易。 只需在HTML页面中使用

可以通过以下方式访问Knockout.js -

  • 您可以从其官方网站下载Knockout.js的生产版本

    将显示如下图所示的页面。 点击下载链接,您将获得最新的knockout.js文件。

Knockoutjs设置

现在请参考以下代码中显示的文件。

<script type = 'text/javascript' src = 'knockout-3.3.0.js'></script>

更新src属性以匹配保存下载文件的位置。

  • 您可以从CDNs参考KnockoutJS库 -

<script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" 
   type = "text/javascript"></script>
  • 或者,您可以从CDNJS引用缩小版的KnockoutJS库,如下所示 -

<script src = "https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js" 
   type = "text/javascript"></script>

Note - 在本教程的所有章节中,我们都提到了KnockoutJS库的CDN版本。

例子 (Example)

KnockoutJS基于Model-View-ViewModel(MVVM)模式。 我们将在KnockoutJS - MVVM Framework一章中深入研究这种模式。 首先让我们来看一个KnockoutJS的简单示例。

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Simple Example</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" 
         type = "text/javascript"></script>
   </head>
   <body>
      <!-- This is called "view" of HTML markup that defines the appearance of UI -->
      <p>First String: <input data-bind = "value: firstString" /></p>
      <p>Second String: <input data-bind = "value: secondString" /></p>
      <p>First String: <strong data-bind = "text: firstString">Hi</strong></p>
      <p>Second String: <strong data-bind = "text: secondString">There</strong></p>
      <p>Derived String: <strong data-bind = "text: thirdString"></strong></p>
      <script>
         <!-- This is called "viewmodel". This javascript section defines the data and 
            behavior of UI -->
         function AppViewModel() {
            this.firstString = ko.observable("Enter First String");
            this.secondString = ko.observable("Enter Second String");
            this.thirdString = ko.computed(function() {
               return this.firstString() + " " + this.secondString();
            }, this);
         }
         // Activates knockout.js
         ko.applyBindings(new AppViewModel());
      </script>
   </body>
</html>

以下行是指KnockoutJS库。

<script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" 
   type = "text/javascript"> </script>

这一行是指KnockoutJS库。

我们有两个输入框: First StringSecond String 。 这两个变量在ViewModel中分别使用值Enter First String和Enter Second String进行初始化。

<p>First String: < input data-bind = "value: firstString" /> </p>

这就是我们如何使用body部分中的'data-bind'属性'data-bind' ViewModel中的值绑定到HTML元素。

这里,'firstString'指的是ViewModel变量。

this.firstString = ko.observable("Enter First String");

ko.observable是一个关注值变化的概念,以便它可以更新底层的ViewModel数据。

为了更好地理解这一点,让我们将第一个输入框更新为“Hello”,将第二个输入框更新为“IoWiki”。 您将看到值同时更新。 我们将在KnockoutJS - Observables章节中更多地研究这个概念。

this.thirdString = ko.computed(function() {
   return this.firstString() + " " + this.secondString();
}, this);

接下来,我们在viewmodel中计算了函数。 此函数基于前面提到的2个字符串派生第三个字符串。 因此,对这些字符串所做的任何更新都会自动反映在此派生字符串中。 无需编写额外的代码即可完成此任务。 这只是一个简单的例子。 我们将在KnockoutJS - Computed Observables章节中研究这个概念。

输出 (Output)

将上面的代码保存为my_first_knockoutjs_program.html 。 在浏览器中打开此文件,您将看到如下输出。

第一个例子

将字符串修改为“Hello”和“IoWiki”,输出更改如下。

您好IoWiki示例

KnockoutJS - Application

KnockoutJS广泛用于单页应用程序 - 一个创建的网站,能够通过单页负载动态检索所有必要的数据,从而减少服务器往返次数。

KnockoutJS是一个客户端框架。 这是一个JavaScript库,可以很容易地将HTML绑定到域数据。 它实现了一个名为Model-View-ViewModel(MVVM)的模式。 Observables是KnockoutJS的神奇成分。 由于Observable属性,所有数据保持同步。

结构 (Architecture)

KnockoutJS架构

View

View只是使用HTML元素和CSS样式创建的用户界面。

您可以使用KnockoutJS将HTML DOM元素绑定到数据模型。 它使用“数据绑定”概念在View和ViewModel之间提供双向数据绑定,这意味着在UI中完成的任何更新都会反映在数据模型中,并且在数据模型中完成的任何更改都会反映在UI中。 可以在knockoutJS的帮助下创建自我更新的UI。

ViewModel (ViewModel)

ViewModel是一个JavaScript对象,它包含表示数据所必需的属性和函数。 View和ViewModel通过HTML中使用的声明性数据绑定概念连接在一起。 这样可以在不更改ViewModel的情况下轻松更改HTML。 KnockoutJS通过使用Observables来处理它们之间的自动数据刷新。

通过将DOM元素绑定到数据模型来实现数据同步,首先使用数据绑定,然后通过使用Observable来刷新这两个组件。 由于数据同步,依赖性跟踪自动完成。 无需额外编码即可实现。 KnockoutJS允许在显示和底层数据之间创建直接连接。

您可以创建自己的绑定,称为应用程序特定行为的自定义绑定。 通过这种方式,Knockout可以直接控制您希望如何将数据转换为HTML。

模型 (Model)

Model是服务器上的域数据,当从ViewModel发送/接收请求时,它会被操纵。

数据可以存储在数据库,cookie或其他形式的持久存储中。 KnockoutJS不担心它是如何存储的。 程序员可以在存储的数据和KnockoutJS之间进行通信。

大多数情况下,数据都是通过Ajax调用保存和加载的。

KnockoutJS - MVVM Framework

Model-View-ViewModel (MVVM)是用于开发软件应用程序的架构设计模式。 MVVM由Microsoft Architect John Gossman于2005年开发。该模式源自模型 - 视图 - 控制器(MVC)模式。 MVVM的优势在于它将应用程序层的图形用户界面与业务逻辑分开。 MVVM负责处理来自底层模型的数据,以便非常容易地表示和管理它。 MVVM中的ViewModel表示View的状态和操作的抽象版本。

视图类不知道Model和ViewModel类是否存在,Model和ViewModel也不知道View存在。 Model也不知道ViewModel和View存在。

结构 (Architecture)

MVVM架构

View

View是使用标记语言创建的图形用户界面来表示数据。 View通过数据绑定概念绑定到ViewModel的属性,该概念间接连接到模型数据。 对于在ViewModel中完成的任何更改,无需更改视图。 由于绑定,对ViewModel中的数据所做的更改会自动在View中传播。

模型 (Model)

模型是域数据或业务对象,它保存实时数据。 模型不带有行为。 行为主要在业务逻辑中实现。

ViewModel (ViewModel)

ViewModel是中心位置,来自Model和View的显示逻辑的数据捆绑在一起。 ViewModel保存数据的动态状态。 View和ViewModel之间有一个隐式绑定器可以相互通信。 此绑定包含声明性数据和命令绑定。 通过此绑定实现View和ViewModel的同步。 View中所做的任何更改都会反映在ViewModel中,同样ViewModel中的任何更改都会自动反映在View中。 这种双向绑定机制的存在是这个MVVM模式的一个关键方面。

KnockoutJS - Observables

KnockoutJS基于以下3个重要概念。

  • 它们之间的可观察性和依赖性跟踪 - DOM元素通过“data-bind”连接到ViewModel。 他们通过Observables交换信息。 这会自动处理依赖关系跟踪。

  • UI和ViewModel之间的声明性绑定 - DOM元素通过“data-bind”概念连接到ViewModel。

  • 模板化以创建可重用的组件 - 模板化提供了一种创建复杂Web应用程序的可靠方法。

我们将在本章中研究Observables。

正如名称所指定的那样,当您将ViewModel数据/属性声明为Observable时,每次数据修改都会自动反映在使用数据的所有位置。 这还包括刷新相关的依赖项。 KO负责这些事情,没有必要编写额外的代码来实现这一目标。

使用Observable,可以非常轻松地使UI和ViewModel动态通信。

语法 (Syntax)

您只需要使用函数ko.observable()声明ViewModel属性,使其成为Observable。

this.property = ko.observable('value');

例子 (Example)

让我们看一下下面的例子,它演示了Observable的用法。

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Observable Example</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" 
         type = "text/javascript"></script>
   </head>
   <body>
      <!-- This is called "view" of HTML markup that defines the appearance of UI -->
      <p>Enter your name: <input data-bind = "value: yourName" /></p>
      <p>Hi <strong data-bind = "text: yourName"></strong> Good Morning!!!</p>
      <script>
         <!-- This is called "viewmodel". This javascript section defines the data and behavior of UI -->
         function AppViewModel() {
            this.yourName = ko.observable("");
         }
         // Activates knockout.js
         ko.applyBindings(new AppViewModel());
      </script>
   </body>
</html>

以下行用于输入框。 可以看出,我们使用data-bind属性将yourName值绑定到ViewModel。

<p>Enter your name: <input data-bind = "value: yourName" /> <p>

以下行只打印yourName的值。 注意,这里数据绑定类型是文本,因为我们只是读取值。

<p>Hi <strong data-bind = "text: yourName"></strong> Good Morning!!!</p>

在以下行中,ko.observable会密切关注yourName变量以进行数据中的任何修改。 一旦进行了修改,相应的位置也会使用修改后的值进行更新。 运行以下代码时,将出现一个输入框。 当您更新该输入框时,新值将在任何使用它的位置反映或刷新。

this.yourName = ko.observable("");

输出 (Output)

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

  • 将以上代码保存在first_observable_pgm.htm文件中。

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

  • 输入名称为Scott,并观察该名称是否反映在输出中。

新页面打开

可以从UI或ViewModel进行数据修改。 无论数据在何处更改,UI和ViewModel都会在它们之间保持同步。 这使它成为一种双向约束机制。 在上面的示例中,当您在输入框中更改名称时,ViewModel将获取新值。 从ViewModel内部更改yourName属性时,UI会收到一个新值。

阅读和写作可观察者

下表列出了可在Observable上执行的读写操作。

Sr.No. 读/写操作和语法
1

Read

要读取值,只需调用不带参数的Observable属性,如:AppViewModel.yourName();

2

Write

要在Observable属性中写入/更新值,只需在参数中传递所需的值,如:AppViewModel.yourName('Bob');

3

Write multiple

借助于链接语法,可以在一行中更新多个ViewModel属性,如:AppViewModel.yourName('Bob')。yourAge(45);

可观察数组

可观察声明负责单个对象的数据修改。 ObservableArray使用对象集合。 当您处理包含多种类型值的复杂应用程序并根据用户操作频繁更改其状态时,这是一个非常有用的功能。

语法 (Syntax)

this.arrayName = ko.observableArray();    // It's an empty array

可观察数组仅跟踪添加或删除其中的对象。 它不会通知是否修改了单个对象的属性。

首次初始化

您可以初始化数组,同时可以通过将初始值传递给构造函数来将其声明为Observable,如下所示。

this.arrayName = ko.observableArray(['scott','jack']);

从Observable Array读取

您可以按如下方式访问Observable数组元素。

alert('The second element is ' + arrayName()[1]);

可观测的数组函数 (Observable Array Functions)

KnockoutJS有自己的一组Observable数组函数。 它们很方便,因为 -

  • 这些功能适用于所有浏览器。

  • 这些功能将自动处理依赖性跟踪。

  • 语法很容易使用。 例如,要将元素插入数组,只需使用arrayName.push('value')而不是arrayName()。push('value')。

以下是各种Observable Array方法的列表。

Sr.No. 方法和描述
1 push('value')

在数组末尾插入一个新项。

2 pop()

从数组中删除最后一项并返回它。

3 unshift('value')

在数组的开头插入一个新值。

4 shift()

从数组中删除第一项并返回它。

5 reverse()

反转数组的顺序。

6 sort()

按升序对数组项进行排序。

7 splice(start-index,end-index)

接受2个参数 - start-index和end-index - 从开始到结束索引中删除项目并将它们作为数组返回。

8 indexOf('value')

此函数返回第一次出现的参数的索引。

9 slice(start-index,end-index)

这个方法切出一个数组。 返回从start-index到end-index的项目。

10 removeAll()

删除所有项目并将其作为数组返回。

11 remove('value')

删除与参数匹配的项并作为数组返回。

12 remove(function(item) { condition })

删除满足条件的项目并将其作为数组返回。

13 remove([set of values])

删除与给定值集匹配的项。

14

destroyAll()

使用值为true的属性_destroy标记数组中的所有项。

15

destroy('value')

搜索等于参数的项目,并使用值为true的特殊属性_destroy标记它。

16

destroy(function(item) { condition})

查找满足条件的所有项目,使用具有true值的属性_destroy标记它们。

17

destroy([set of values])

查找与给定值集匹配的项,将它们标记为具有true值的_destroy。

Note - ObservableArrays中的Destroy和DestroyAll函数主要用于'Ruby on Rails'开发人员。

当您使用destroy方法时,相应的项目当时并未真正从数组中删除,但是通过使用属性_destroy标记它们来使其隐藏,以便UI无法读取它们。 标记为_destroy等于true项目将在以后处理JSON对象图时删除。

KnockoutJS - Computed Observables

Computed Observable是一个依赖于一个或多个Observable的函数,只要其基础Observable(依赖项)发生变化,它就会自动更新。

计算的Observable可以链接。

语法 (Syntax)

this.varName = ko.computed(function(){
   ...
   ... //  function code
   ...
},this);

例子 (Example)

让我们看一下下面的例子,它演示了Computed Observables的用法。

<!DOCTYPE html>
   <head >
      <title>KnockoutJS Computed Observables</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js"></script>
   </head>
   <body>
      <p>Enter first number: <input data-bind = "value: a" /></p>
      <p>Enter second number: <input data-bind = "value: b"/></p>
      <p>Average := <span data-bind="text: totalAvg"></span></p>
      <script>
         function MyViewModel() {
            this.a = ko.observable(10);
            this.b = ko.observable(40);
            this.totalAvg = ko.computed(function() {
               if(typeof(this.a()) !== "number" || typeof(this.b()) !== "number") {
                  this.a(Number(this.a()));   //convert string to Number
                  this.b(Number(this.b()));   //convert string to Number
               }
               total = (this.a() + this.b())/2 ;
               return total;
            },this);
         }
         ko.applyBindings(new MyViewModel());
      </script>
   </body>
</html>

在以下行中,前两行用于接受输入值。 第三行打印这两个数字的平均值。

<p>Enter first number: <input data-bind = "value: a" /></p>
<p>Enter second number: <input data-bind = "value: b"/></p>
<p>Average := <span data-bind = "text: totalAvg"></span></p>

在以下行中,Observables ab类型是在ViewModel中首次初始化时的数字。 但是,在KO中,从UI接受的每个输入都默认为String格式。 因此需要将它们转换为Number以便对它们执行算术运算。

this.totalAvg = ko.computed(function() {
   if(typeof(this.a()) !== "number" || typeof(this.b()) !== "number") {
      this.a(Number(this.a()));   //convert string to Number
      this.b(Number(this.b()));   //convert string to Number
   }
   total = (this.a() + this.b())/2 ;
   return total;
},this);

在以下行中,计算的平均值显示在UI中。 请注意,totalAvg的数据绑定类型只是文本。

<p>Average := <span data-bind = "text: totalAvg"></span></p>

输出 (Output)

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

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

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

  • 在文本框中输入任意2个数字,并观察计算平均值。

新页面打开

管理'这个'

请注意,在上面的示例中,第二个参数作为Computed函数提供。 如果不提供this参考,则无法引用Observables a()b()

为了克服这个问题,使用self变量来保持其参考。 这样做,无需在整个代码中跟踪this 。 相反,可以使用self

使用self为以上示例重写ViewModel代码。

function MyViewModel(){
   self = this;
   self.a = ko.observable(10);
   self.b = ko.observable(40);
   this.totalAvg = ko.computed(function() {
      if(typeof(self.a()) !== "number" || typeof(self.b()) !== "number") {
         self.a(Number(self.a()));   //convert string to Number
         self.b(Number(self.b()));   //convert string to Number
      }
      total = (self.a() + self.b())/2 ;
      return total;
   });
}

纯计算可观测量

如果Observable只是计算并返回值而不是直接修改其他对象或状态,则应将Computed Observable声明为Pure Computed Observable。 Pure Computed Observables帮助Knockout有效地管理重新评估和内存使用。

明确通知订阅者

当Computed Observable返回原始数据类型值(String,Boolean,Null和Number)时,当且仅当实际值发生更改时,才会通知其订阅者。 这意味着如果Observable收到的值与之前的值相同,则不会通知其订阅者。

您可以使Computed Observables始终显式通知观察者,即使新值与旧值相同,使用notify语法如下所示。

myViewModel.property = ko.pureComputed(function() {
   return ...;    // code logic goes here
}).extend({ notify: 'always' });

限制变更通知

太多昂贵的更新可能会导致性能问题。 您可以使用rateLimit属性限制从Observable接收的通知数,如下所示。

// make sure there are updates no more than once per 100-millisecond period
myViewModel.property.extend({ rateLimit: 100 });

如果某个属性是可计算的,则可以找到

在某些情况下,可能需要查明属性是否为Computed Observable。 以下函数可用于标识Observable的类型。

Sr.No. 功能
1

ko.isComputed

如果属性为Computed Observable,则返回true

2

ko.isObservable

如果属性是Observable,Observable array或Computed Observable,则返回true

3

ko.isWritableObservable

如果是Observable,Observable数组或Writable Computed Observable,则返回true 。 (这也称为ko.isWriteableObservable)

可写的计算可观测量

Computed Observable派生自一个或多个其他Observable,因此它是只读的。 但是,有可能使Computed Observable可写。 为此,您需要提供适用于写入值的回调函数。

这些可写的Computed Observable就像常规的Observable一样工作。 此外,它们还需要构建自定义逻辑来干扰读写操作。

可以使用链接语法为多个Observables或Computed Observable属性赋值,如下所示。

myViewModel.fullName('Tom Smith').age(45)

例子 (Example)

下面的示例演示了Writable Computable Observable的使用。

<!DOCTYPE html>
   <head >
      <title>KnockoutJS Writable Computed Observable</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"></script>
   </head>
   <body>
      <p>Enter your birth Date: <input type = "date" data-bind = "value: rawDate" ></p>
      <p><span data-bind = "text: yourAge"></span></p>
      <script>
         function MyViewModel() {
            this.yourAge = ko.observable();
            today = new Date();
            rawDate = ko.observable();
            this.rawDate = ko.pureComputed ({
               read: function() {
                  return this.yourAge;
               },
               write: function(value) {
                  var b = Date.parse(value);    // convert birth date into milliseconds
                  var t = Date.parse(today);    // convert todays date into milliseconds
                  diff = t - b;                 // take difference
                  var y = Math.floor(diff/31449600000);     // difference is converted
                                                            // into years. 31449600000
                                                            //milliseconds form a year.
                  var m = Math.floor((diff % 31449600000)/604800000/4.3);  // calculating
                                                                           // months.
                                                                           // 604800000
                                                                           // milliseconds
                                                                           // form a week.
                  this.yourAge("You are " + y + " year(s) " + m +" months old.");
               },
               owner: this
            });
         }
         ko.applyBindings(new MyViewModel());
      </script>
   </body>
</html>

在上面的代码中, rawDate是从UI接受的pureComputed属性。 yourAge Observable派生自rawDate

JavaScript中的日期以毫秒为单位进行操作。 因此,日期(今天日期和出生日期)都转换为毫秒,然后它们之间的差异将以年和月的形式转换回来。

输出 (Output)

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

  • 将上述代码保存在writable_computed_observable.htm文件中。

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

  • 输入任何出生日期并观察年龄的计算。

新页面打开

KnockoutJS - Declarative Bindings

KnockoutJS中的声明性绑定提供了一种将数据连接到UI的强大方法。

了解绑定和Observable之间的关系非常重要。 从技术上讲,这两者是不同的。 您可以使用普通的JavaScript对象作为ViewModel,KnockoutJS可以正确处理View的绑定。

如果没有Observable,UI中的属性将仅首次处理。 在这种情况下,它无法根据基础数据更新自动更新。 要实现此目的,必须将绑定引用到Observable属性。

绑定语法

绑定由2个项组成,即绑定namevalue 。 以下是一个简单的例子 -

Today is : <span data-bind = "text: whatDay"></span>

这里,text是绑定名称,whatDay是绑定值。 您可以使用逗号分隔多个绑定,如以下语法所示。

Your name: <input data-bind = "value: yourName, valueUpdate: 'afterkeydown'" />

在这里,按下每个键后更新值。

绑定值

绑定值可以是single valueliteralvariable ,也可以是JavaScript表达式。 如果绑定引用了某些无效的表达式或引用,则KO将产生错误并停止处理绑定。

以下是几个绑定的例子。

<!-- simple text binding -->
<p>Enter employee name: <input   -bind = 'value: empName' /></p>
<!-- click binding, call a specific function -->
<button data-bind="click: sortEmpArray">Sort Array</button>
<!-- options binding -->
<select multiple = "true" size = "8" data-bind = "options: empArray , 
   selectedOptions: chosenItem"> </select>

请注意以下几点 -

  • 空格没有任何区别。

  • 从KO 3.0开始,您可以跳过绑定值,该绑定值将为绑定提供未定义的值。

绑定上下文

当前绑定中使用的数据可以由对象引用。 此对象称为binding context

上下文层次结构由KnockoutJS自动创建和管理。 下表列出了KO提供的不同类型的绑定上下文。

Sr.No. 绑定上下文类型和描述
1

$root

这总是指顶级ViewModel。 这使得可以访问操作ViewModel的顶级方法。 这通常是对象,传递给ko.applyBindings。

2

$data

这个属性很像Javascript对象中的this关键字。 绑定上下文中的$ data属性引用当前上下文的ViewModel对象。

3

$index

此属性包含foreach循环内数组的当前项的索引。 当更新基础Observable数组时,$ index的值将自动更改。 显然,此上下文仅适用于foreach绑定。

4

$parent

此属性引用父ViewModel对象。 当您想要从嵌套循环内部访问外部ViewModel属性时,这非常有用。

5

$parentContext

在父级别绑定的上下文对象称为$parentContext 。 这与$parent不同。 $ parent指的是数据。 而$parentContext指的是绑定上下文。 例如,您可能需要从内部上下文访问外部foreach项的索引。

6

$rawdata

此上下文在当前情况下保存原始ViewModel值。 这类似于$ data,但区别在于,如果ViewModel包含在Observable中,那么$ data就会被解包。 ViewModel和$ rawdata成为实际的Observable数据。

7

$component

当您在特定组件内时,此上下文用于引用该组件的ViewModel。 例如,您可能希望从ViewModel访问某些属性,而不是组件的模板部分中的当前数据。

8

$componentTemplateNodes

这表示当您在特定组件模板中时传递给该特定组件的DOM节点数组。

以下术语也可用于绑定,但实际上不是绑定上下文。

  • $context - 这只是现有的绑定上下文对象。

  • $element - 此对象引用当前绑定中DOM中的元素。

使用文本和外观

以下是KO提供的用于处理文本和视觉外观的绑定类型列表。

Sr.No. 绑定类型和用法
1 visible: <binding-condition>

根据特定条件显示或隐藏HTML DOM元素。

2 text:<binding-value>

设置HTML DOM元素的内容。

3 html:<binding-value>

设置DOM元素的HTML标记内容。

4 css:<binding-object>

将CSS类应用于元素。

5 style:<binding-object>

定义元素的内联样式属性。

6 attr:<binding-object>

要动态地向元素添加属性。

使用控制流绑定

以下是KO提供的控制流绑定类型列表。

Sr.No. 绑定类型和用法
1 foreach:<binding-array>

在此绑定中,每个数组项都在循环中的HTML标记中引用。

2 if:<binding-condition>

如果条件为真,则将处理给定的HTML标记。 否则,它将从DOM中删除。

3 ifnot:<binding-condition>

If的否定。 如果条件为真,则将处理给定的HTML标记。 否则,它将从DOM中删除。

4 with:<binding-object>

此绑定用于绑定指定对象上下文中对象的子元素。

5 component:<component-name> OR component:<component-object>

此绑定用于将组件插入DOM元素并可选地传递参数。

使用表单字段绑定

以下是KO提供的表单字段绑定类型列表。

Sr.No. 绑定类型和用法
1 click: <binding-function>

此绑定用于基于单击调用与DOM元素关联的JavaScript函数。

2 event:<DOM-event:handler-function>

此绑定用于侦听指定的DOM事件并基于它们调用关联的处理函数。

3 submit: <binding-function>

此绑定用于在提交关联的DOM元素时调用JavaScript函数。

4 enable:<binding-value>

此绑定用于根据指定的条件启用某些DOM元素。

5 disable:<binding-value>

当参数计算结果为true时,此绑定将禁用关联的DOM元素。

6 value:<binding-value>

此绑定用于将相应DOM元素的值链接到ViewModel属性。

7 textInput:<binding-value>

此绑定用于在文本框或textarea与ViewModel属性之间创建双向绑定。

8 hasFocus:<binding-value>

此绑定用于通过ViewModel属性手动设置HTML DOM元素的焦点。

9 checked: <binding-value>

此绑定用于在可检查表单元素和ViewModel属性之间创建链接。

10 options:<binding-array>

此绑定用于定义select元素的选项。

11 selectedOptions:<binding-array>

此绑定用于处理当前在多列表选择表单控件中选择的元素。

12 uniqueName:<binding-value>

此绑定用于为DOM元素生成唯一名称。

KnockoutJS - Dependency Tracking

KnockoutJs会在值更新时自动跟踪依赖项。 它有一个称为dependency tracker (ko.dependencyDetection)的对象,它充当了双方之间用于订阅依赖关系的中间件。

以下是依赖性跟踪的算法。

依赖追踪

Step 1 - 每当您声明一个计算的observable时,KO立即调用其求值函数来获取其初始值。

Step 2 - 订阅被设置为评估者读取的任何可观察对象。 在应用程序中,处理不再使用的旧订阅。

Step 3 - KO最终通知更新的计算的observable。

Example

<!DOCTYPE html>
<html>
   <head>
      <title>KnockoutJS How Dependency Tracking Works</title>
      <!-- CDN's-->
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js"
         type = "text/javascript"></script>
   </head>
   <body>
      <div>
         <form data-bind = "submit: addFruits">
            <b>Add Fruits:</b>
            <input data-bind = 'value: fruitToAdd, valueUpdate: "afterkeydown"'/>
            <button type = "submit" data-bind = "enable: fruitToAdd().length > 0">Add</button>
            <p><b>Your fruits list:</b></p>
            <select multiple = "multiple" width = "50" data-bind = "options: fruits"> </select>
         </form>
      </div>
      <script>
         var Addfruit = function(fruits) {
            this.fruits = ko.observableArray(fruits);
            this.fruitToAdd = ko.observable("");
            this.addFruits = function() {
               if (this.fruitToAdd() != "") {
                  this.fruits.push(this.fruitToAdd());   // Adds a fruit
                  this.fruitToAdd("");                   // Clears the text box
               }
            }.bind(this);                                // "this" is the view model
         };
         ko.applyBindings(new Addfruit(["Apple", "Orange", "Banana"]));
      </script>
   </body>
</html>

Output

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

  • 将以上代码保存在dependency_tracking.htm文件中。

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

  • 输入任何水果名称,然后单击“添加”按钮。

新页面打开

使用Peek控制依赖关系

通过使用peek函数,可以在不创建依赖项的情况下访问Computed Observable。 它通过更新计算属性来控制Observable。

Example

<!DOCTYPE html>
<html>
   <head>
      <title>KnockoutJs Controlling Dependencies Using Peek</title>
      <!-- CDN's-->
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js"
         type = "text/javascript"></script>
   </head>
   <body>
      <div class = "logblock">
         <h3>Computed Log</h3>
         <pre class = "log" data-bind = "html: computedLog"></pre>
      </div>
      <script>
         function AppData() {
            this.firstName = ko.observable('John');
            this.lastName = ko.observable('Burns');
            this.computedLog = ko.observable('Log: ');
            this.fullName = ko.computed(function () {
               var value = this.firstName() + " " + this.lastName();
               this.computedLog(this.computedLog.peek() + value + '; <br/>');
               return value;
            }, this);
            this.step = ko.observable(0);
            this.next = function () {
               this.step(this.step() === 2 ? 0 : this.step()+1);
            };
         };
         ko.applyBindings(new AppData());
      </script>
   </body>
</html>

Output

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

  • 将以上代码保存在dependency_tracking_peek.htm文件中。

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

新页面打开

观察 (Observations)

忽略计算依赖关系中的依赖关系

ko.ignoreDependencies函数有助于忽略您不希望在计算的依赖项中跟踪的那些依赖项。 以下是它的语法。

ko.ignoreDependencies( callback, callbackTarget, callbackArgs );

为什么循环依赖没有意义

如果KO正在评估Computed Observable,那么它将不会重新启动对依赖Computed Observable的评估。 因此,在依赖链中包含循环是没有意义的。

KnockoutJS - Templating

Template是一组可以重复使用的DOM元素。 模板化使得构建复杂应用程序变得容易,因为它具有最小化DOM元素重复的特性。

有两种创建模板的方法。

  • Native templating - 此方法支持控制流绑定,例如foreach,with和if。 这些绑定捕获元素中存在的HTML标记,并将其用作随机项的模板。 此模板不需要外部库。

  • String-based templating - KO连接到第三方引擎以将ViewModel值传递到其中,并将生成的标记注入到文档中。 例如,JQuery.tmpl和Underscore Engine。

Syntax

template: <parameter-value>
<script type = "text/html" id = "template-name">
   ...
   ...   // DOM elemets to be processed
   ...
</script>

请注意, type在脚本块中以text/html type提供,以通知KO,它不是可执行块,而只是需要呈现的模板块。

Parameters

可以将以下属性的组合作为参数值发送到模板。

  • name - 表示模板的名称。

  • nodes - 这表示要用作模板的DOM节点数组。 如果传递name参数,则忽略此参数。

  • data - 这只是通过模板显示的数据。

  • if - 如果给定条件导致true或true-like值,将提供模板。

  • foreach - 以foreach格式提供模板。

  • as - 这只是在foreach元素中创建一个别名。

  • afterAdd, afterRender, beforeRemove - 这些都是表示根据执行的操作执行的可调用函数。

观察 (Observations)

渲染命名模板

当与控制流绑定一起使用时,模板由DOM内的HTML标记隐式定义。 但是,如果您愿意,可以将模板分解为单独的元素,然后按名称引用它们。

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - Named Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
   </head>
   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <div data-bind = "template: { name: 'friend-template', data: friend1 }"></div>
      <div data-bind = "template: { name: 'friend-template', data: friend2 }"></div>
      <script type = "text/html" id = "friend-template">
         <h3 data-bind = "text: name"></h3>
         <p>Contact Number: <span data-bind = "text: contactNumber"></span></p>
         <p>Email-id: <span data-bind = "text: email"></span></p>
      </script>
      <script type = "text/javascript">
         function MyViewModel() {
            this.friend1 = { 
               name: 'Smith', 
               contactNumber: 4556750345, 
               email: 'smith123@gmail.com' 
            };
            this.friend2 = { 
               name: 'Jack', 
               contactNumber: 6789358001, 
               email: 'jack123@yahoo.com' 
            };
         }
         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
   </body>
</html>

Output

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

  • 将以上代码保存在template-named.htm文件中。

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

  • 这里,friend-template使用了2次。

新页面打开

在模板中使用“foreach”

以下是使用foreach参数和模板名称的示例。

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - foreach used with Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
   </head>
   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <div data-bind = "template: { name: 'friend-template', foreach: friends }"></div>
      <script type = "text/html" id = "friend-template">
         <h3 data-bind = "text: name"></h3>
         <p>Contact Number: <span data-bind = "text: contactNumber"></span></p>
         <p>Email-id: <span data-bind = "text: email"></span></p>
      </script>
      <script type = "text/javascript">
         function MyViewModel() {
            this.friends = [
               { name: 'Smith', contactNumber: 4556750345, email: 'smith123@gmail.com' },
               { name: 'Jack', contactNumber: 6789358001, email: 'jack123@yahoo.com' },
               { name: 'Lisa', contactNumber: 4567893131, email: 'lisa343@yahoo.com' }
            ]
         }
         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
   </body>
</html>

Output

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

  • 将以上代码保存在template-foreach.htm文件中。

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

  • 这里,foreach控件用于模板绑定。

新页面打开

使用asach项的关键字创建别名

以下是如何为foreach项创建别名 -

<div data-bind = "template: { 
   name: 'friend-template', 
   foreach: friends, 
   as: 'frnz' 
}"></div>

通过创建别名,可以很容易地从foreach循环内部引用父对象。 当代码很复杂并且嵌套在多个级别时,此功能非常有用。

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - using alias in Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
   </head>
   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <ul data-bind = "template: { 
         name: 'friend-template', 
         foreach: friends, 
         as: 'frnz' 
      }"></ul>
      <script type = "text/html" id = "friend-template">
         <li>
            <h3 data-bind = "text: name"></h3>
            <span>Contact Numbers</span>
            <ul data-bind = "template: { 
               name : 'contacts-template', 
               foreach:contactNumber, 
               as: 'cont'
            } "></ul>
            <p>Email-id: <span data-bind = "text: email"></span></p>
         </li>
      </script>
      <script type = "text/html" id = "contacts-template">
         <li>
            <p><span data-bind = "text: cont"></span></p>
         </li>
      </script>
      <script type = "text/javascript">
         function MyViewModel() {
            this.friends = ko.observableArray ( [
               { 
                  name: 'Smith', 
                  contactNumber: [ 4556750345, 4356787934 ], 
                  email: 'smith123@gmail.com' 
               },
               { 
                  name: 'Jack', 
                  contactNumber: [ 6789358001, 3456895445 ], 
                  email: 'jack123@yahoo.com' 
               },
               { 
                  name: 'Lisa', 
                  contactNumber: [ 4567893131, 9876456783, 1349873445 ],  
                  email: 'lisa343@yahoo.com' 
               }
            ]);
         }
         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
   </body>
</html>

Output

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

  • 将以上代码保存在template-as-alias.htm文件中。

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

  • 使用别名而不是数组的全名。

新页面打开

使用afterAdd,beforeRemove和afterRender

在某些情况下,需要在模板创建的DOM元素上运行额外的自定义逻辑。 在这种情况下,可以使用以下回调。 考虑一下你正在使用foreach元素 -

afterAdd - 当一个新项添加到foreach中提到的数组时调用此函数。

beforeRemove - 在从foreach中提到的数组中删除项目之前调用此函数。

afterRender - 每次呈现foreach并将新条目添加到数组时,都会调用此处提到的函数。

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - Use of afterRender Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
      <script src = "https://code.jquery.com/jquery-2.1.3.min.js"
         type = "text/javascript"></script>
   </head>
   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <div data-bind = "template: { 
         name: 'friend-template', 
         foreach: friends , 
         afterRender: afterProcess
      }"></div>
      <script type = "text/html" id = "friend-template">
         <h3 data-bind = "text: name"></h3>
         <p>Contact Number: <span data-bind = "text: contactNumber"></span></p>
         <p>Email-id: <span data-bind = "text: email"></span></p>
         <button data-bind = "click: $root.removeContact">remove </button>
      </script>
      <script type = "text/javascript">
         function MyViewModel() {
            self = this;
            this.friends = ko.observableArray ([
               { name: 'Smith', contactNumber: 4556750345, email: 'smith123@gmail.com' },
               { name: 'Jack', contactNumber: 6789358001, email: 'jack123@yahoo.com' },
            ])
            this.afterProcess = function(elements, data){
               $(elements).css({color: 'magenta' });
            }
            self.removeContact = function() {
               self.friends.remove(this);
            }
         }
         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
   </body>
</html>

Output

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

  • 将以上代码保存在template-afterrender.htm文件中。

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

  • 这里,每次渲染foreach时都会执行afterProcess函数。

新页面打开

动态选择模板

如果有多个模板可用,则可以通过将名称设置为observable参数来动态选择一个模板。 因此,模板值将在名称参数更改时重新评估,然后将重新呈现数据。

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - Dynamic Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
   </head>
   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <div data-bind = "template: { 
         name: whichTemplate, 
         foreach: friends 
      }"></div>
      <script type = "text/html" id = "only-phon">
         <h3 data-bind = "text: name"></h3>
         <p>Contact Number: <span data-bind = "text: contactNumber"></span></p>
      </script>
      <script type = "text/html" id = "only-email">
         <h3 data-bind = "text: name"></h3>
         <p>Email-id: <span data-bind = "text: email"></span></p>
      </script>
      <script type = "text/javascript">
         function MyViewModel() {
            this.friends = ko.observableArray ([
               {
                  name: 'Smith', 
                  contactNumber: 4556750345, 
                  email: 'smith123@gmail.com', 
                  active: ko.observable(true)
               },
               {
                  name: 'Jack', 
                  contactNumber: 6789358001, 
                  email: 'jack123@yahoo.com', 
                  active: ko.observable(false)
               },
            ]);
            this.whichTemplate = function(friends) {
               return friends.active() ? "only-phon" : "only-email";
            }
         }
         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
   </body>
</html>

Output

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

  • 将以上代码保存在template-dynamic.htm文件中。

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

  • 要使用的模板取决于活动标志值。

新页面打开

使用外部字符串引擎

即使使用嵌套代码块,本机模板也可与各种控制流元素完美配合。 KO还提供了一种与外部模板库集成的方法,例如Underscore模板引擎或JQuery.tmpl。

正如官方网站上所提到的,自2011年12月以来,JQuery.tmpl已不再处于活跃开发阶段。因此,仅建议使用KO的本机模板而不是JQuery.tmpl或任何其他基于字符串的模板引擎。

有关详细信息,请参阅官方网站

KnockoutJS - Components

组件是组织UI代码以构建大型应用程序和提高代码可重用性的一种巨大方式。

它是从其他组件继承或嵌套的。 对于加载和配置,它定义了自己的约定或逻辑。

它被打包以在整个应用程序或项目中重用。 表示应用程序或小控件/小部件的完整部分。 它可以按需加载或预加载。

组件注册

组件可以使用ko.components.register() API进行注册。 它有助于加载和表示KO中的组件。 配置的组件名称需要注册。 配置指定如何确定viewModel和模板。

Syntax

组件可以注册如下 -

ko.components.register('component-name', {
   viewModel: {...},    //function code
   template: {....)	//function code
});
  • component-name可以是任何非空字符串。

  • viewModel是可选的,可以采用下一节中列出的任何viewModel格式。

  • template是必需的,可以采用下一节中列出的任何模板格式。

陈述ViewModel

下表列出了可用于注册组件的viewModel格式。

Sr.No. viewModel表单和描述
1

constructor function

它为每个组件创建一个单独的viewModel对象。 对象或函数用于绑定组件视图。

function SomeComponentViewModel(params) {
   this.someProperty = params.something;
}
ko.components.register('component name', {
   viewModel: SomeComponentViewModel,
   template: ...
});
2

shared object instance

viewModel对象实例是共享的。 传递实例属性以直接使用该对象。

var sharedViewModelInstance = { ... };
ko.components.register('component name', {
   viewModel: { instance: sharedViewModelInstance },
   template: ...
});
3

createViewModel

它调用一个充当工厂的函数,可以用作可以返回对象的视图模型。

ko.components.register('component name', {  
   viewModel: {  
      createViewModel: function (params, componentInfo) {  
         ...       //function code  
         ...
      }  
   },  
   template: ....  
});
4

AMD module

它是一种模块格式,用于定义模块和依赖项都是异步加载的模块。

ko.components.register('component name', {
   viewModel: { require: 'some/module/name' },
   template: ...
});
define(['knockout'], function(ko) {
   function MyViewModel() {
      // ...
   }
   return MyViewModel;
});

陈述模板

下表列出了可用于注册组件的模板格式。

Sr.No. 模板表格
1

element ID

ko.components.register('component name', {
   template: { element: 'component-template' },
   viewModel: ...
});
2

element instance

var elemInstance = document.getElementById('component-template');
ko.components.register('component name', {
   template: { element: elemInstance },
   viewModel: ...
});
3

string of markup

ko.components.register('component name', {
   template: '<input data-bind = "value: yourName" />\
      <button data-bind = "click: addEmp">Add Emp </button>',
   viewModel: ...
});
4

DOM nodes

var emp = [
   document.getElementById('node 1'),
   document.getElementById('node 2'),
];
ko.components.register('component name', {
   template: emp,
   viewModel: ...
});
5

document fragement

ko.components.register('component name', {
   template: someDocumentFragmentInstance,
   viewModel: ...
});
6

AMD module

ko.components.register('component name', {
   template: { require: 'some/template' },
   viewModel: ...
});

注册为单个AMD模块的组件

AMD模块可以自行注册组件,而无需使用viewModel/template对。

ko.components.register('component name',{ require: 'some/module'});

组件绑定

组件绑定有两种方式。

  • Full syntax - 它将参数和对象传递给组件。 它可以使用以下属性传递。

    • name - 添加组件名称。

    • params - 它可以在组件上的对象中传递多个参数。

<div data-bind='component: {
   name: "tutorials point",
   params: { mode: "detailed-list", items: productsList }
}'>
</div>
  • Shorthand syntax - 它将字符串作为组件名称传递,并且不包含参数。

<div data-bind = 'component: "component name"'></div>
  • Template-only components - 组件只能在不指定viewModel的情况下定义模板。

ko.components.register('component name', {
   template:'<input data-bind = "value: someName" />,
});
  • Using Component without a container element Component - 可以在不使用额外容器元素的情况下使用组件。 这可以使用与评论标签类似的无containerless flow控制来完成。

<!--ko.component: ""-->
<!--/ko-->

自定义元素

自定义元素是一种渲染组件的方法。 在这里,您可以直接编写自描述标记元素名称,而不是定义占位符,其中组件通过它进行绑定。

<products-list params = "name: userName, type: userType"></products-list>

传递参数

params属性用于将参数传递给组件viewModel。 它类似于data-bind属性。 params属性的内容被解释为JavaScript对象文字(就像数据绑定属性一样),因此您可以传递任何类型的任意值。 它可以通过以下方式传递参数 -

  • Communication between parent and child components - 组件本身不是实例化的,因此视图模型属性是从组件外部引用的,因此将由子组件视图模型接收。 例如,您可以在以下语法中看到ModelValue是父视图模型,它由子视图模型构造函数ModelProperty接收。

  • Passing observable expressions - 它在params参数中有三个值。

    • simpleExpression - 这是一个数值。 它不涉及任何可观察者。

    • simpleObservable - 它是在父viewModel上定义的实例。 父viewModel将自动获取子viewModel对observable所做的更改。

    • observableExpression - 当表达式由其自身计算时,表达式读取observable。 当可观察值发生变化时,表达式的结果也会随着时间的推移而变化。

我们可以传递如下参数 -

<some-component
   params = 'simpleExpression: 1 + 1,
      simpleObservable: myObservable,
      observableExpression: myObservable() + 1'>
</some-component>

我们可以在viewModel中传递参数,如下所示 -

<some-component
   params = 'objectValue:{a: 3, b: 2},
      dateValue: new date(),
      stringValue: "Hi",
      numericValue:123,
      boolValue: true/false,
      ModelProperty: ModelValue'>
</some-component>

将标记传递给组件

接收的标记用于创建组件,并选择作为输出的一部分。 以下节点作为组件模板中输出的一部分传递。

template: { nodes: $componentTemplateNodes }

控制自定义元素标记名称

使用ko.components.register在组件中注册的名称,相同的名称对应于自定义元素标记名称。 我们可以通过覆盖它来控制使用getComponentNameForNode来更改自定义元素标记名称。

ko.components.getComponentNameForNode = function(node) {
   ...
   ...   //function code
   ...
}

注册自定义元素

如果使用默认的组件加载器,则可以立即使用自定义元素,因此使用ko.components.register注册组件。 如果我们不使用ko.components.register并实现自定义组件加载器,则可以通过定义任何选择的元素名称来使用自定义元素。 使用ko.components.register时无需指定配置,因为自定义组件加载器不再使用它。

ko.components.register('custom-element', { ......... });

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Components</title>
      <script src = "https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      <script src = "https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
   </head>
   <body>
      <!--params attribute is used to pass the parameter to component viewModel.-->
      <click params = "a: a, b: b"></click>
      <!--template is used for a component by specifying its ID -->
      <template id = "click-l">
         <div data-bind = "text: a"></div>
         <!--Use data-bind attribute to bind click:function() to ViewModel. -->
         <button data-bind = "click:function(){callback(1)}">Increase</button>
         <button data-bind = "click:function(){callback(-1)}">Decrease</button>
      </template>
      <script>
         //Here components are registered
         ko.components.register('click', {
            viewModel: function(params) {
               self = this;
               this.a = params.a;
               this.b = params.b;
               this.callback = function(num) {
                  self.b(parseInt(num));
                  self.a( self.a() + parseInt(num) );
               };
            },
            template: { element: 'click-l' }
         });
         //keeps an eye on variable for any modification in data
         function viewModel() {
            this.a = ko.observable(2);
            this.b = ko.observable(0);
         }
         ko.applyBindings(new viewModel() );
      </script>
   </body>
</html>

Output

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

  • 将以上代码保存在component_register.htm文件中。

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

新页面打开

组件装载机

组件加载器用于为给定的组件名称异步传递模板/ viewModel对。

默认的组件加载器

默认组件加载器取决于显式注册的配置。 在使用组件之前注册每个组件。

ko.components.defaultLoader

组件加载器实用函数 (Component Loader Utility Functions)

默认组件加载程序可以使用以下函数进行读写。

Sr.No. 实用功能和说明
1

ko.components.register(name, configuration)

组件已注册。

2

ko.components.isRegistered(name)

如果已注册特定组件名称,则返回true,否则返回false。

3

ko.components.unregister(name)

组件名称将从注册表中删除。

4

ko.components.get(name, callback)

该函数依次转到每个已注册的加载器,以查找谁已经通过组件名称的viewModel/template定义作为第一个。 然后它通过调用callback返回viewModel/template声明。 如果已注册的加载器无法找到有关该组件的任何信息,则会调用callback(null)

5

ko.components.clearCachedDefinition(name)

当我们想要清除给定的组件缓存条目时,可以调用此函数。 如果下次需要该组件,则将再次查询装载机。

实现自定义组件加载器

自定义组件加载器可以通过以下方式实现 -

  • getConfig(name, callback) - 根据名称,我们可以以编程方式传递配置。 我们可以调用callback(componentConfig)来传递配置,其中对象componentConfig可以被loadComponent或任何其他加载器使用。

  • loadComponent(name, componentConfig, callback) - 此函数根据配置方式解析viewModel和config的模板部分。 我们可以调用callback(result)来传递viewmodel/template对,其中对象结果由以下属性定义。

    • template - 必填。 返回DOM节点数组。

    • createViewModel(params, componentInfo) - 可选。 返回viewModel对象,具体取决于viewModel属性的配置方式。

  • loadTemplate(name, templateConfig, callback) - 使用自定义逻辑在模板中传递DOM节点。 对象templateConfig是来自对象componentConfig的模板的属性。 调用callback(domNodeArray)来传递DOM节点数组。

  • loadViewModel(name, templateConfig, callback) - 使用自定义逻辑在viewModel配置中传递viewModel工厂。

↑回到顶部↑
WIKI教程 @2018