(Knockout版本:3.4.1 )
KO的组件主要从如下四个部分进行详细介绍:javascript
1.组件的定义和注册
2.组件绑定
3.使用自定义元素
4.自定义组件加载器(高级)html
1.经过"视图模型"、"模版"配对注册组件java
--1.1 指定视图模型的方法
----1.1.1 构造函数
----1.1.2 对象实例
----1.1.3 创造视图模型的工厂函数
----1.1.4 AMD模块,其值描述了一个视图模型node
--1.2 指定模版的方法
----1.2.1 已存在元素的ID
----1.2.2 已存在元素的实例
----1.2.3 HTML字符串
----1.2.4 包含许多DOM节点的数组
----1.2.5 文档片断
----1.2.6 AMD模块,其值描述了一个模版web
2.Knockout怎样经过AMD加载组件数组
--2.1 AMD模块为按需加载浏览器
3.经过一个AMD模块注册组件dom
--3.1 推荐的AMD组件模块的定义方式函数
function SomeComponentViewModel(params) { // 'params' is an object whose key/value pairs are the parameters // passed from the component binding or custom element. this.someProperty = params.something; } SomeComponentViewModel.prototype.doSomething = function() { ... }; ko.components.register('my-component', { viewModel: SomeComponentViewModel, template: ... });
Knockout将会调用这个构造函数并生成一个实例做为视图模型,其中params参数在组件调用的时候传入。post
直接传递一个对象实例做为视图模型,全部使用这个对象的组件共享这一个实例。假定对象实例为modelInstance,注意传入方法为:viewModel: {instance: modelInstance}
若是建立这个视图模型须要取得一些组件调用的信息,那么就采起这从模式定义视图模型。
ko.components.register('my-component', { viewModel: { createViewModel: function(params, componentInfo) { // - 'params'是组件调用时传入的对象 // - 'componentInfo.element'是组件注入的元素,当createViewModel方 // 法被调用时,组件已被注入到元素中,但尚未发生绑定。 // - 'componentInfo.templateNodes'是一个包含了组件调用时内部的DOM节 // 点的数组。 // 经过本身定义的构造函数返回一个实例 return new MyViewModel(params); } }, template: ... });
注意,操做DOM最好只经过自定义绑定,而不要经过componentInfo.element进行一些操做DOM的行为。
componentInfo.templateNodes在咱们须要控制组件输出的节点时会起到做用。
若是使用了AMD模块加载器,好比(require.js),可使用模块加载器直接加载AMD模块做为视图模型。
ko.components.register('my-component', { viewModel: { require: 'some/module/name' }, template: ... });
加载的AMD模块只要按照1.1.1,1.1.2,1.1.3三种方式中的一种提供模块(即returns)就能够了。另外还有一种通常不会用到的方式AMD模块的return为 return { module: 'some/other/module' }
,这种方式将会加载其它模块。
<template id='my-component-template'> <h1 data-bind='text: title'></h1> <button data-bind='click: doSomething'>Click me right now</button> </template> ko.components.register('my-component', { template: { element: 'my-component-template' }, viewModel: ... });
指定一个已存在元素的ID便可,ID所对应元素自己不会被做为模版的元素传入,其内部节点会做为模版被传入。推荐使用例子里的< template>标签,别的标签也能够,但浏览器不识别template标签因此它不会被渲染收到影响,另外语义也比较清晰。
相似于传入ID,只是此次传入的是元素实例。
ko.components.register('my-component', { template: '<h1 data-bind="text: title"></h1>\ <button data-bind="click: doSomething">Clickety</button>', viewModel: ... });
当咱们从别处取得一些字符串来生成模版时(好比AMD),这个方法颇有用。
var myNodes = [ document.getElementById('first-node'), document.getElementById('second-node'), document.getElementById('third-node') ]; ko.components.register('my-component', { template: myNodes, viewModel: ... });
这些节点会依次做为组件模版被复制渲染出来。
能够传一个AMD模块,这个模块的返回值是以上模版的任一种类型均可以。
2.Knockout怎样经过AMD加载组件
当为视图模型和模版传入require声明时:
ko.components.register('my-component', { viewModel: { require: 'some/module/name' }, template: { require: 'text!some-template.html' } });
这些AMD模块被加载,实际上相似于使用了require(['some/module/name'], callback)
和require(['text!some-template.html'], callback)
。KO加载这些模块有三个须要注意的点:
*KO并不严格要求使用require.js,任何其它的AMD模块加载器均可以使用。
*KO并不影响加载模块的路径,路径仍然彻底由所用的AMD加载器决定。
*KO并不关心所加载的模块是不是暴露了全局变量名称的模块。
好比一个组件写在了一个绑定了if指令的标签中,那只有if对应的值真,组件模块才加载,不然不加载。若是组件模块已经加载过了, 那么将再也不发送HTTP请求来请求模块,而是预加载以前存下来的模块。
只要AMD模块返回的是以上任意一种合法的模块配置就能够做为一个有效的组件模块,可是有一种推荐的组件模块定义方法:
// - 使用这种模式定义模块的优势在于 // - 引入只须要一个require声明 // - 能够被require.js的r.js打包 define(['knockout', 'text!./my-component.html'], function(ko, htmlString) { function MyComponentViewModel(params) { // 在这里设置属性等 } // 使用原型定义公共方法 MyComponentViewModel.prototype.doSomething = function() { ... }; // 返回组件的定义 return { viewModel: MyComponentViewModel, template: htmlString }; });
这样定义的组件模块,调用方法为:ko.components.register('my-component', { require: 'path/my-component' });
。一个组件模块由两个文件组成,一个视图模型(path/my-component.js)和一个模版(path/my-component.html),建立天然,维护方便。