- KnockoutJS 教程
- KnockoutJS - 首頁
- KnockoutJS - 概述
- KnockoutJS - 環境設定
- KnockoutJS - 應用
- KnockoutJS - MVVM 框架
- KnockoutJS - 可觀察物件
- 計算可觀察物件
- KnockoutJS - 宣告式繫結
- KnockoutJS - 依賴跟蹤
- KnockoutJS - 模板
- KnockoutJS - 元件
- KnockoutJS 資源
- KnockoutJS - 快速指南
- KnockoutJS - 資源
- KnockoutJS - 討論
KnockoutJS - 元件
元件是組織大型應用程式UI程式碼、構建結構和提高程式碼可重用性的一種重要方式。
它繼承自或巢狀於其他元件。對於載入和配置,它定義了自己的約定或邏輯。
它被打包以便在整個應用程式或專案中重用。代表應用程式的完整部分或小型控制元件/部件。它可以按需載入或預載入。
元件註冊
元件可以使用ko.components.register() API 註冊。它有助於在 KO 中載入和表示元件。註冊需要元件名稱和配置。配置指定如何確定viewModel和模板。
語法
元件可以按如下方式註冊:
ko.components.register('component-name', {
viewModel: {...}, //function code
template: {....) //function code
});
元件名稱可以是任何非空字串。
viewModel是可選的,可以採用下一節列出的任何viewModel格式。
template是必需的,可以採用下一節列出的任何模板格式。
宣告ViewModel
下表列出了可以用來註冊元件的viewModel格式。
| 序號 | viewModel格式及說明 |
|---|---|
| 1 | 建構函式 它為每個元件建立一個單獨的viewModel物件。該物件或函式用於繫結到元件檢視。 function SomeComponentViewModel(params) {
this.someProperty = params.something;
}
ko.components.register('component name', {
viewModel: SomeComponentViewModel,
template: ...
});
|
| 2 | 共享物件例項 viewModel物件例項是共享的。傳遞instance屬性以直接使用該物件。 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模組 這是一種用於定義模組的模組格式,其中模組和依賴項都是非同步載入的。 ko.components.register('component name', {
viewModel: { require: 'some/module/name' },
template: ...
});
define(['knockout'], function(ko) {
function MyViewModel() {
// ...
}
return MyViewModel;
});
|
宣告模板
下表列出了可以用來註冊元件的模板格式。
| 序號 | 模板格式 |
|---|---|
| 1 | 元素ID ko.components.register('component name', {
template: { element: 'component-template' },
viewModel: ...
});
|
| 2 | 元素例項 var elemInstance = document.getElementById('component-template');
ko.components.register('component name', {
template: { element: elemInstance },
viewModel: ...
});
|
| 3 | 標記字串 ko.components.register('component name', {
template: '<input data-bind = "value: yourName" />\
<button data-bind = "click: addEmp">Add Emp </button>',
viewModel: ...
});
|
| 4 | DOM節點 var emp = [
document.getElementById('node 1'),
document.getElementById('node 2'),
];
ko.components.register('component name', {
template: emp,
viewModel: ...
});
|
| 5 | 文件片段 ko.components.register('component name', {
template: someDocumentFragmentInstance,
viewModel: ...
});
|
| 6 | AMD模組 ko.components.register('component name', {
template: { require: 'some/template' },
viewModel: ...
});
|
作為單個AMD模組註冊的元件
AMD模組本身可以註冊元件,無需使用viewModel/template對。
ko.components.register('component name',{ require: 'some/module'});
元件繫結
有兩種元件繫結方式。
完整語法 - 它將引數和物件傳遞給元件。它可以使用以下屬性傳遞。
name - 新增元件名稱。
params - 它可以在元件上以物件形式傳遞多個引數。
<div data-bind='component: {
name: "tutorials point",
params: { mode: "detailed-list", items: productsList }
}'>
</div>
簡寫語法 - 它將字串作為元件名稱傳遞,並且不包含引數。
<div data-bind = 'component: "component name"'></div>
僅模板元件 - 元件只能定義模板,而不指定viewModel。
ko.components.register('component name', {
template:'<input data-bind = "value: someName" />,
});
無需容器元素即可使用元件 - 元件無需使用額外的容器元素即可使用。這可以透過使用無容器流控制來完成,這類似於註釋標籤。
<!--ko.component: ""--> <!--/ko-->
自定義元素
自定義元素是渲染元件的一種方式。在這裡,您可以直接編寫自描述的標記元素名稱,而不是定義佔位符,元件透過它進行繫結。
<products-list params = "name: userName, type: userType"></products-list>
傳遞引數
params屬性用於將引數傳遞給元件viewModel。它類似於data-bind屬性。params屬性的內容被解釋為JavaScript物件文字(就像data-bind屬性一樣),因此您可以傳遞任何型別的任意值。它可以按以下方式傳遞引數:
父元件和子元件之間的通訊 - 元件本身不會被例項化,因此viewmodel屬性是從元件外部引用的,因此將被子元件viewmodel接收。例如,您可以在下面的語法中看到ModelValue是父viewmodel,它被子viewmodel建構函式ModelProperty接收。
傳遞可觀察表示式 - params引數中有三個值。
simpleExpression - 它是一個數值。它不涉及任何可觀察物件。
simpleObservable - 它是定義在父viewModel上的例項。父viewModel將自動獲取子viewModel對可觀察物件所做的更改。
observableExpression - 表示式在表示式本身被求值時讀取可觀察物件。當可觀察物件的值發生變化時,表示式的結果也會隨著時間而變化。
我們可以按如下方式傳遞引數:
<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', { ......... });
示例
<!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>
輸出
讓我們執行以下步驟來檢視上述程式碼是如何工作的:
將上述程式碼儲存在component_register.htm檔案中。
在瀏覽器中開啟此HTML檔案。
元件載入器
元件載入器用於為給定的元件名稱非同步傳遞template/viewModel對。
預設元件載入器
預設元件載入器取決於顯式註冊的配置。每個元件在使用前都會被註冊。
ko.components.defaultLoader
元件載入器實用函式
預設元件載入器可以使用以下函式進行讀寫。
| 序號 | 實用函式及說明 |
|---|---|
| 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) - 此函式根據配置方式解析config的viewModel和template部分。我們可以呼叫callback(result)來傳遞viewmodel/template對,其中物件result由以下屬性定義。
template - 必需。返回DOM節點陣列。
createViewModel(params, componentInfo) - 可選。根據viewModel屬性的配置方式返回viewModel物件。
loadTemplate(name, templateConfig, callback) - 使用自定義邏輯在模板中傳遞DOM節點。物件templateConfig是來自物件componentConfig的模板的屬性。callback(domNodeArray)被呼叫以傳遞DOM節點陣列。
loadViewModel(name, templateConfig, callback) - 使用自定義邏輯在viewModel配置中傳遞viewModel工廠。