Components (组件)是一个强大的,干净的方式组织您的UI代码,可重复使用的块。 :
- …可以表示单独的控件/窗口小部件或应用程序的整个部分
- …包含自己的视图,通常(但可选)自己的视图模型
- …可以预加载或通过AMD或其他模块系统异步加载(按需)
- …可以接收参数,并可选地将更改写回到它们或调用回调
- …可以一起组成(嵌套)或继承自其他组件
- …可以轻松地打包,以便跨项目进行重用
- …让您定义自己的约定/逻辑进行配置和加载
此模式有利于大型应用程序,因为它通过明确的组织和封装简化了开发,并通过根据需要增量式加载应用程序代码和模板来帮助提高运行时性能。
自定义元素是用于消费组件的可选但方便的语法。 不需要使用绑定注入组件的占位符<div>,您可以使用具有自定义元素名称的更多自描述标记(例如,<voting-button>或<product-editor>)。 Knockout小心确保兼容性,即使与旧的浏览器,如IE 6。
示例1:喜欢/不喜欢小部件
可以使用ko.components.register注册组件(技术上,注册是可选的,但它是最简单的入门方式)。 组件定义指定一个viewModel和模板。 例如:
ko.components.register('like-widget', { viewModel: function(params) { // Data: value is either null, 'like', or 'dislike' this.chosenValue = params.value; // Behaviors this.like = function() { this.chosenValue('like'); }.bind(this); this.dislike = function() { this.chosenValue('dislike'); }.bind(this); }, template: '<div class="like-or-dislike" data-bind="visible: !chosenValue()"> <button data-bind="click: like">Like it</button> <button data-bind="click: dislike">Dislike it</button> </div> <div class="result" data-bind="visible: chosenValue"> You <strong data-bind="text: chosenValue"></strong> it </div>' });
通常,您将从外部文件加载视图模型和模板,而不是像这样声明它们。
现在,要使用此组件,您可以从应用程序中的任何其他视图引用它,可以使用组件绑定或使用自定义元素。 下面是一个使用它作为自定义元素的实例:
UI源码:
<ul data-bind="foreach: products"> <li class="product"> <strong data-bind="text: name"></strong> <like-widget params="value: userRating"></like-widget> </li> </ul>
视图模型源码:
function Product(name, rating) { this.name = name; this.userRating = ko.observable(rating || null); } function MyViewModel() { this.products = [ new Product('Garlic bread'), new Product('Pain au chocolat'), new Product('Seagull spaghetti', 'like') // This one was already 'liked' ]; } ko.components.register('like-widget', { viewModel: function(params) { // Data: value is either null, 'like', or 'dislike' this.chosenValue = params.value; // Behaviors this.like = function() { this.chosenValue('like'); }.bind(this); this.dislike = function() { this.chosenValue('dislike'); }.bind(this); }, template: '<div class="like-or-dislike" data-bind="visible: !chosenValue()"> <button data-bind="click: like">Like it</button> <button data-bind="click: dislike">Dislike it</button> </div> <div class="result" data-bind="visible: chosenValue"> You <strong data-bind="text: chosenValue"></strong> it </div>' }); ko.applyBindings(new MyViewModel());
在本示例中,组件可以显示和编辑一个名为“产品视图模型类”上的“用户评级”的observable属性。
示例2:根据需要从外部文件加载类似/不喜欢小部件
在大多数应用程序中,您需要将组件视图模型和模板保留在外部文件中。 如果将Knockout配置为通过AMD模块加载器(如require.js)获取它们,那么可以预加载(可能捆绑/缩减)或根据需要增量加载它们。
下面是一个配置示例:
ko.components.register('like-or-dislike', { viewModel: { require: 'files/component-like-widget' }, template: { require: 'text!files/component-like-widget.html' } });
要求
为了这个工作,文件files / component-like-widget.js和files / component-like-widget.html需要存在。 检查出来(并查看源代码上的.html) - 正如你将看到的,这是更清洁和更方便的,包括定义中的内联代码。
此外,您需要引用一个合适的模块加载器库(例如require.js)或实现一个知道如何抓取您的文件的自定义组件加载器。
使用组件
现在喜欢或不喜欢可以像以前一样使用组件绑定或自定义元素:
UI源码:
<ul data-bind="foreach: products"> <li class="product"> <strong data-bind="text: name"></strong> <like-or-dislike params="value: userRating"></like-or-dislike> </li> </ul> <button data-bind="click: addProduct">Add a product</button>
视图模型源码:
function Product(name, rating) { this.name = name; this.userRating = ko.observable(rating || null); } function MyViewModel() { this.products = ko.observableArray(); // Start empty } MyViewModel.prototype.addProduct = function() { var name = 'Product ' + (this.products().length + 1); this.products.push(new Product(name)); }; ko.applyBindings(new MyViewModel());
如果您在首次单击“添加产品”之前打开浏览器开发人员工具的“网络检查器”,您会看到组件的.js / .html文件在首次需要时被抓取,然后保留以供重用。