组件(Components)

优质
小牛编辑
169浏览
2023-12-01

组件是组织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工厂。