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工廠。

廣告
© . All rights reserved.