组件(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对象。 对象或函数用于绑定组件视图。
|
2 | shared object instance viewModel对象实例是共享的。 传递实例属性以直接使用该对象。
|
3 | createViewModel 它调用一个充当工厂的函数,可以用作可以返回对象的视图模型。
|
4 | AMD module 它是一种模块格式,用于定义模块和依赖项都是异步加载的模块。
|
陈述模板
下表列出了可用于注册组件的模板格式。
Sr.No. | 模板表格 |
---|---|
1 | element ID
|
2 | element instance
|
3 | string of markup
|
4 | DOM nodes
|
5 | document fragement
|
6 | AMD module
|
注册为单个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工厂。