KnockoutJS - Краткое руководство

KnockoutJS - это, по сути, библиотека, написанная на JavaScript, основанная на шаблоне MVVM, который помогает разработчикам создавать многофункциональные и адаптивные веб-сайты. Модель разделяет модель приложения (сохраненные данные), представление (пользовательский интерфейс) и модель представления (представление модели в JavaScript).

KnockoutJS был разработан и поддерживается как проект с открытым исходным кодом Стивом Сандерсоном, сотрудником Microsoft 5 июля 2010 года. KO - это сокращение, используемое для KnockoutJS. KO поддерживает все основные браузеры - IE 6+, Firefox 3.5+, Chrome, Opera, Safari (настольный / мобильный).

Особенности KnockoutJS

Вот список некоторых из наиболее заметных функций KnockoutJS:

  • Declarative Binding- Элементы HTML DOM связаны с моделью через атрибут data-bind с использованием очень простого синтаксиса. Благодаря этой функции легко добиться отзывчивости.

  • Automatic UI Refresh- Любые изменения, внесенные для просмотра данных модели, автоматически отображаются в пользовательском интерфейсе и наоборот. Нет необходимости писать дополнительный код.

  • Dependency Tracking- Связь между атрибутами KO и функциями / компонентами библиотеки KO прозрачна. Автоматически отслеживает изменения данных в атрибуте KO и обновляет соответствующие затронутые области.

  • Templating - Шаблоны - это простой и удобный способ создания сложных структур пользовательского интерфейса с возможностью повторения или вложения блоков в зависимости от данных модели представления.

  • Extensible - Очень легко расширяет настраиваемое поведение.

Зачем использовать KnockoutJS?

  • Библиотека KnockoutJS обеспечивает простой и понятный способ обработки сложных интерфейсов, управляемых данными. Можно создавать самообновляющиеся пользовательские интерфейсы для объектов Javascript.

  • Это чистая библиотека JavaScript, работающая с любым веб-фреймворком. Это не замена JQuery, но может работать как дополнение, предоставляя интеллектуальные функции.

  • Файл библиотеки KnockoutJS очень маленький и легкий.

  • KnockoutJS не зависит от других фреймворков. Он совместим с другими технологиями на стороне клиента или сервера.

  • Самое главное, что KnockoutJS имеет открытый исходный код и, следовательно, бесплатен для использования.

  • KnockoutJS полностью документирован. На официальном сайте есть полная документация, включая документацию по API, живые примеры и интерактивные руководства.

KnockoutJS очень прост в использовании. Просто укажите файл JavaScript с помощью тега <script> на страницах HTML.

Knockout.js можно получить следующими способами:

  • Вы можете скачать производственную сборку Knockout.js с официального сайта.

    Будет отображена страница, показанная на следующем изображении. Щелкните ссылку для загрузки, и вы получите последний файл knockout.js.

Теперь обратитесь к файлу, как показано в следующем коде.

<script type = 'text/javascript' src = 'knockout-3.3.0.js'></script>

Обновите атрибут src, чтобы он соответствовал местоположению, в котором хранятся загруженные файлы.

  • Вы можете обратиться к библиотеке KnockoutJS из CDN -

    • Вы можете ссылаться на библиотеку KnockoutJS из Microsoft Ajax CDN в своем коде следующим образом:

<script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" 
   type = "text/javascript"></script>
  • В качестве альтернативы вы можете обратиться к уменьшенной версии библиотеки KnockoutJS из CDNJS следующим образом:

<script src = "https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js" 
   type = "text/javascript"></script>

Note - Во всех главах этого руководства мы упоминали CDN-версию библиотеки KnockoutJS.

пример

KnockoutJS основан на шаблоне Model-View-ViewModel (MVVM). Мы подробно изучим этот шаблон в главе KnockoutJS - MVVM Framework . Сначала рассмотрим простой пример KnockoutJS.

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Simple Example</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" 
         type = "text/javascript"></script>
   </head>

   <body>
      <!-- This is called "view" of HTML markup that defines the appearance of UI -->

      <p>First String: <input data-bind = "value: firstString" /></p>
      <p>Second String: <input data-bind = "value: secondString" /></p>

      <p>First String: <strong data-bind = "text: firstString">Hi</strong></p>
      <p>Second String: <strong data-bind = "text: secondString">There</strong></p>

      <p>Derived String: <strong data-bind = "text: thirdString"></strong></p>

      <script>
         <!-- This is called "viewmodel". This javascript section defines the data and 
            behavior of UI -->

         function AppViewModel() {
            this.firstString = ko.observable("Enter First String");
            this.secondString = ko.observable("Enter Second String");

            this.thirdString = ko.computed(function() {
               return this.firstString() + " " + this.secondString();
            }, this);
         }

         // Activates knockout.js
         ko.applyBindings(new AppViewModel());
      </script>

   </body>
</html>

Следующая строка относится к библиотеке KnockoutJS.

<script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" 
   type = "text/javascript"> </script>

Эта строка относится к библиотеке KnockoutJS.

У нас есть два поля ввода: First String и Second String. Эти две переменные инициализируются значениями Enter First String и Enter Second String соответственно в ViewModel.

<p>First String: < input data-bind = "value: firstString" /> </p>

Вот как мы привязываем значения из ViewModel к элементам HTML, используя 'data-bind' атрибут в разделе body.

Здесь firstString относится к переменной ViewModel.

this.firstString = ko.observable("Enter First String");

ko.observable - это концепция, которая следит за изменениями значений, чтобы обновлять базовые данные ViewModel.

Чтобы лучше понять это, давайте обновим первое поле ввода на «Hello», а второе поле ввода на «TutorialsPoint». Вы увидите, что значения обновляются одновременно. Подробнее об этой концепции мы поговорим в главе KnockoutJS - Observables .

this.thirdString = ko.computed(function() {
   return this.firstString() + " " + this.secondString();
}, this);

Затем мы вычислили функцию в модели просмотра. Эта функция выводит третью строку на основе двух упомянутых ранее строк. Таким образом, любые обновления, внесенные в эти строки, автоматически отражаются в этой производной строке. Для этого не нужно писать дополнительный код. Это всего лишь простой пример. Мы изучим эту концепцию в главе KnockoutJS - Computed Observables .

Вывод

Сохраните приведенный выше код как my_first_knockoutjs_program.html. Откройте этот файл в своем браузере, и вы увидите следующий результат.

Измените строки на «Hello» и «TutorialsPoint», и результат изменится следующим образом.

KnockoutJS широко используется для одностраничных приложений - веб-сайт, созданный с возможностью динамического извлечения всех необходимых данных с помощью одной страницы, что снижает количество обращений к серверу.

KnockoutJS - это фреймворк на стороне клиента. Это библиотека JavaScript, которая упрощает привязку HTML к данным домена. Он реализует шаблон под названием Model-View-ViewModel (MVVM). Observables - волшебный ингредиент KnockoutJS. Все данные остаются синхронизированными из-за атрибута Observable.

Архитектура

Посмотреть

Представление - это не что иное, как пользовательский интерфейс, созданный с использованием элементов HTML и стилей CSS.

Вы можете привязать элементы HTML DOM к модели данных с помощью KnockoutJS. Он обеспечивает двустороннюю привязку данных между View и ViewModel с использованием концепции привязки данных, что означает, что любые обновления, сделанные в пользовательском интерфейсе, отражаются в модели данных, а любые изменения, сделанные в модели данных, отражаются в пользовательском интерфейсе. Самостоятельно обновляемый пользовательский интерфейс можно создать с помощью knockoutJS.

ViewModel

ViewModel - это объект JavaScript, который содержит необходимые свойства и функции для представления данных. View и ViewModel связаны вместе с концепцией декларативного связывания данных, используемой в HTML. Это упрощает изменение HTML без изменения ViewModel. KnockoutJS заботится об автоматическом обновлении данных между ними с помощью Observables.

Синхронизация данных достигается за счет привязки элементов DOM к модели данных, сначала с помощью привязки данных, а затем обновления этих двух компонентов с помощью Observables. Отслеживание зависимостей выполняется автоматически благодаря этой синхронизации данных. Для этого не требуется никакого дополнительного кодирования. KnockoutJS позволяет создать прямую связь между отображением и базовыми данными.

Вы можете создавать свои собственные привязки, называемые настраиваемыми привязками, для поведения конкретных приложений. Таким образом, Knockout дает прямой контроль над тем, как вы хотите преобразовать свои данные в HTML.

Модель

Модель - это данные домена на сервере, и ими манипулируют по мере отправки / получения запроса от ViewModel.

Данные могут храниться в базе данных, файлах cookie или другом постоянном хранилище. KnockoutJS не заботится о том, как он хранится. Программист должен обмениваться данными между сохраненными данными и KnockoutJS.

В большинстве случаев данные сохраняются и загружаются через вызов Ajax.

Model-View-ViewModel (MVVM)- это шаблон архитектурного проектирования для разработки программных приложений. MVVM был разработан архитектором Microsoft Джоном Госсманом в 2005 году. Этот шаблон унаследован от шаблона модель-представление-контроллер (MVC). Преимущество MVVM в том, что он отделяет графический пользовательский интерфейс прикладного уровня от бизнес-логики. MVVM отвечает за обработку данных из базовой модели таким образом, чтобы они представлялись и управлялись очень легко. ViewModel в MVVM представляет абстрактную версию состояния и действий View.

Классы представления не знают о существовании классов Model и ViewModel, а также Model и ViewModel не знают о существовании View. Модель также не знает, что ViewModel и View существуют.

Архитектура

Посмотреть

Представление - это графический пользовательский интерфейс, созданный с использованием языка разметки для представления данных. View привязывается к свойствам ViewModel через концепцию привязки данных, которая косвенно подключается к данным модели. Вид не нужно менять при любых изменениях, сделанных в ViewModel. Изменения, внесенные в данные в ViewModel, автоматически распространяются в View из-за привязки.

Модель

Модель - это данные предметной области или бизнес-объект, который содержит данные в реальном времени. Модель не несет в себе поведения. Поведение в основном реализовано в бизнес-логике.

ViewModel

ViewModel - это центральное место, где объединяются данные из логики отображения модели и представления. ViewModel хранит динамическое состояние данных. Между View и ViewModel существует неявная связка для взаимодействия друг с другом. Эта привязка включает декларативные данные и привязку команд. Синхронизация View и ViewModel достигается за счет этой привязки. Любое изменение, сделанное в View, отражается в ViewModel, и аналогичным образом любое изменение в ViewModel автоматически отражается в View. Существование этого механизма двустороннего связывания является ключевым аспектом этого шаблона MVVM.

KnockoutJS основан на следующих трех важных концепциях.

  • Наблюдаемые объекты и отслеживание зависимостей между ними - элементы DOM подключаются к ViewModel через привязку данных. Они обмениваются информацией через Observables. Это автоматически позаботится об отслеживании зависимостей.

  • Декларативные привязки между пользовательским интерфейсом и ViewModel - элементы DOM связаны с ViewModel через концепцию привязки данных.

  • Создание шаблонов для создания повторно используемых компонентов. Шаблоны предоставляют надежный способ создания сложных веб-приложений.

В этой главе мы будем изучать наблюдаемые.

Как указано в названии, когда вы объявляете данные / свойство ViewModel как Observable, любое изменение данных каждый раз автоматически отражается во всех местах использования данных. Это также включает обновление связанных зависимостей. KO позаботится об этом, и для этого нет необходимости писать дополнительный код.

Используя Observable, становится очень легко заставить UI и ViewModel взаимодействовать динамически.

Синтаксис

Вам просто нужно объявить свойство ViewModel с функцией ko.observable() чтобы сделать его наблюдаемым.

this.property = ko.observable('value');

пример

Давайте посмотрим на следующий пример, демонстрирующий использование Observable.

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Observable Example</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" 
         type = "text/javascript"></script>
   </head>
   
   <body>
      <!-- This is called "view" of HTML markup that defines the appearance of UI -->

      <p>Enter your name: <input data-bind = "value: yourName" /></p>
      <p>Hi <strong data-bind = "text: yourName"></strong> Good Morning!!!</p>

      <script>
         <!-- This is called "viewmodel". This javascript section defines the data and behavior of UI -->

         function AppViewModel() {
            this.yourName = ko.observable("");
         }

         // Activates knockout.js
         ko.applyBindings(new AppViewModel());
      </script>
   </body>
</html>

Следующая строка предназначена для поля ввода. Как видно, мы использовали атрибут data-bind для привязки значения yourName к ViewModel.

<p>Enter your name: <input data-bind = "value: yourName" /> <p>

Следующая строка просто печатает значение yourName. Обратите внимание, что здесь тип привязки данных - это текст, поскольку мы просто читаем значение.

<p>Hi <strong data-bind = "text: yourName"></strong> Good Morning!!!</p>

В следующей строке ko.observable следит за переменной yourName на предмет любых изменений в данных. После изменения соответствующие места также обновляются с измененным значением. Когда вы запустите следующий код, появится поле ввода. Когда вы обновляете это поле ввода, новое значение будет отражаться или обновляться в тех местах, где оно используется.

this.yourName = ko.observable("");

Вывод

Давайте выполним следующие шаги, чтобы увидеть, как работает приведенный выше код -

  • Сохраните приведенный выше код в first_observable_pgm.htm файл.

  • Откройте этот HTML-файл в браузере.

  • Введите имя как Скотт и обратите внимание, что имя отражается в выводе.

Изменение данных может происходить либо из пользовательского интерфейса, либо из ViewModel. Независимо от того, где изменяются данные, UI и ViewModel синхронизируют их между собой. Это делает механизм двусторонней привязки. В приведенном выше примере, когда вы меняете свое имя в поле ввода, ViewModel получает новое значение. Когда вы меняете свойство yourName из ViewModel, пользовательский интерфейс получает новое значение.

Чтение и запись наблюдаемых

В следующей таблице перечислены операции чтения и записи, которые могут выполняться на Observables.

Sr.No. Операция чтения / записи и синтаксис
1

Read

Чтобы прочитать значение, просто вызовите свойство Observable без таких параметров, как: AppViewModel.yourName ();

2

Write

Чтобы записать / обновить значение в свойстве Observable, просто передайте желаемое значение в параметре, например: AppViewModel.yourName ('Bob');

3

Write multiple

Несколько свойств ViewModel могут быть обновлены в одной строке с помощью синтаксиса цепочки, например: AppViewModel.yourName ('Bob'). YourAge (45);

Наблюдаемые массивы

Объявление Observable заботится об изменении данных одного объекта. ObservableArray работает с коллекцией объектов. Это очень полезная функция, когда вы имеете дело со сложными приложениями, содержащими несколько типов значений и часто меняющими их статус в зависимости от действий пользователя.

Синтаксис

this.arrayName = ko.observableArray();    // It's an empty array

Наблюдаемый массив только отслеживает, какие объекты в нем добавляются или удаляются. Он не уведомляет об изменении свойств отдельного объекта.

Инициализировать его в первый раз

Вы можете инициализировать свой массив, и в то же время вы можете объявить его как Observable, передав начальные значения в конструктор следующим образом.

this.arrayName = ko.observableArray(['scott','jack']);

Чтение из наблюдаемого массива

Вы можете получить доступ к элементам массива Observable следующим образом.

alert('The second element is ' + arrayName()[1]);

Функции ObservableArray

KnockoutJS имеет собственный набор функций массива Observable. Они удобны тем, что -

  • Эти функции работают во всех браузерах.

  • Эти функции автоматически позаботятся об отслеживании зависимостей.

  • Синтаксис прост в использовании. Например, чтобы вставить элемент в массив, вам просто нужно использовать arrayName.push ('value') вместо arrayName (). Push ('value').

Ниже приведен список различных методов наблюдаемого массива.

Sr.No. Методы и описание
1 push ('значение')

Вставляет новый элемент в конец массива.

2 поп ()

Удаляет последний элемент из массива и возвращает его.

3 unshift ('значение')

Вставляет новое значение в начало массива.

4 сдвиг()

Удаляет первый элемент из массива и возвращает его.

5 обеспечить регресс()

Меняет порядок массива на обратный.

6 Сортировать()

Сортирует элементы массива в порядке возрастания.

7 splice (начальный индекс, конечный индекс)

Принимает 2 параметра - start-index и end-index - удаляет элементы, начиная с начального до конечного индекса, и возвращает их в виде массива.

8 indexOf ('значение')

Эта функция возвращает индекс первого появления предоставленного параметра.

9 срез (начальный индекс, конечный индекс)

Этот метод вырезает часть массива. Возвращает элементы от начального индекса до конечного индекса.

10 убрать все()

Удаляет все элементы и возвращает их в виде массива.

11 удалить ('значение')

Удаляет элементы, соответствующие параметру, и возвращает в виде массива.

12 удалить (функция (элемент) {условие})

Удаляет элементы, удовлетворяющие условию, и возвращает их в виде массива.

13 удалить ([набор значений])

Удаляет элементы, соответствующие заданному набору значений.

14

destroyAll()

Помечает все элементы в массиве свойством _destroy со значением true.

15

destroy('value')

Ищет элемент, равный параметру, и отмечает его специальным свойством _destroy со значением true.

16

destroy(function(item) { condition})

Находит все элементы, удовлетворяющие условию, помечает их свойством _destroy с истинным значением.

17

destroy([set of values])

Находит элементы, которые соответствуют заданному набору значений, помечает их как _destroy с истинным значением.

Note - Функции Destroy и DestroyAll из ObservableArrays в основном предназначены только для разработчиков Ruby on Rails.

Когда вы используете метод destroy, соответствующие элементы на самом деле не удаляются из массива в этот момент, а становятся скрытыми, помечая их свойством _destroy с истинным значением, чтобы они не могли быть прочитаны пользовательским интерфейсом. Элементы, помеченные как _destroy равными true , удаляются позже при работе с графом объектов JSON.

Computed Observable - это функция, которая зависит от одного или нескольких Observable и автоматически обновляется при изменении лежащих в основе Observable (зависимостей).

Вычисляемые наблюдаемые можно связывать в цепочку.

Синтаксис

this.varName = ko.computed(function(){
   ...
   ... //  function code
   ...
},this);

пример

Давайте посмотрим на следующий пример, который демонстрирует использование Computed Observables.

<!DOCTYPE html>
   <head >
      <title>KnockoutJS Computed Observables</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js"></script>
   </head>

   <body>
      <p>Enter first number: <input data-bind = "value: a" /></p>
      <p>Enter second number: <input data-bind = "value: b"/></p>
      <p>Average := <span data-bind="text: totalAvg"></span></p>

      <script>
         function MyViewModel() {
            this.a = ko.observable(10);
            this.b = ko.observable(40);

            this.totalAvg = ko.computed(function() {

               if(typeof(this.a()) !== "number" || typeof(this.b()) !== "number") {
                  this.a(Number(this.a()));   //convert string to Number
                  this.b(Number(this.b()));   //convert string to Number
               }

               total = (this.a() + this.b())/2 ;
               return total;
            },this);
         }

         ko.applyBindings(new MyViewModel());
      </script>

   </body>
</html>

В следующих строках первые две предназначены для приема входных значений. В третьей строке печатается среднее этих двух чисел.

<p>Enter first number: <input data-bind = "value: a" /></p>
<p>Enter second number: <input data-bind = "value: b"/></p>
<p>Average := <span data-bind = "text: totalAvg"></span></p>

В следующих строках тип Observables a и b- это число, когда они инициализируются впервые внутри ViewModel. Однако в KO каждый ввод, принимаемый из пользовательского интерфейса, по умолчанию имеет формат String. Поэтому их нужно преобразовать в числа, чтобы выполнять с ними арифметические операции.

this.totalAvg = ko.computed(function() {
   
   if(typeof(this.a()) !== "number" || typeof(this.b()) !== "number") {
      this.a(Number(this.a()));   //convert string to Number
      this.b(Number(this.b()));   //convert string to Number
   }
   
   total = (this.a() + this.b())/2 ;
   return total;
},this);

В следующей строке вычисленное среднее значение отображается в пользовательском интерфейсе. Обратите внимание, что тип привязки данных totalAvg - это просто текст.

<p>Average := <span data-bind = "text: totalAvg"></span></p>

Вывод

Давайте выполним следующие шаги, чтобы увидеть, как работает приведенный выше код -

  • Сохраните приведенный выше код в computed-observable.htm файл.

  • Откройте этот HTML-файл в браузере.

  • Введите любые 2 числа в текстовые поля и убедитесь, что вычисляется среднее значение.

Управление этим

Обратите внимание, что в приведенном выше примере второй параметр предоставляется как thisк вычисляемой функции. Невозможно сослаться на Observablesa() и b() без предоставления this.

Чтобы преодолеть это, self используется переменная, которая содержит ссылку на this. При этом нет необходимости отслеживатьthisпо всему коду. Вместо,self может быть использован.

Следующий код ViewModel переписан для приведенного выше примера с использованием self.

function MyViewModel(){
   self = this;
   self.a = ko.observable(10);
   self.b = ko.observable(40);

   this.totalAvg = ko.computed(function() {
      
      if(typeof(self.a()) !== "number" || typeof(self.b()) !== "number") {
         self.a(Number(self.a()));   //convert string to Number
         self.b(Number(self.b()));   //convert string to Number
      }
      
      total = (self.a() + self.b())/2 ;
      return total;
   });
}

Чистые вычисленные наблюдаемые

Вычисляемый наблюдаемый должен быть объявлен как PureComputed Observable, если этот Observable просто вычисляет и возвращает значение, а не напрямую изменяет другие объекты или состояние. Pure Computed Observables помогает Knockout эффективно управлять переоценкой и использованием памяти.

Явное уведомление подписчиков

Когда Computed Observable возвращает значение примитивного типа данных (String, Boolean, Null и Number), его подписчики уведомляются тогда и только тогда, когда происходит изменение фактического значения. Это означает, что если Observable получил то же значение, что и предыдущее значение, то его подписчики не уведомляются.

Вы можете сделать так, чтобы Computed Observables всегда явно уведомляла наблюдателей, даже если новое значение совпадает со старым, используя notify синтаксис следующий.

myViewModel.property = ko.pureComputed(function() {
   return ...;    // code logic goes here
}).extend({ notify: 'always' });

Ограничение уведомлений об изменениях

Слишком много дорогих обновлений может привести к проблемам с производительностью. Вы можете ограничить количество уведомлений, получаемых от Observable, используяrateLimit атрибут следующим образом.

// make sure there are updates no more than once per 100-millisecond period
myViewModel.property.extend({ rateLimit: 100 });

Определение того, является ли свойство вычисляемым наблюдаемым

В определенных ситуациях может потребоваться выяснить, является ли свойство вычисляемым наблюдаемым. Следующие функции могут использоваться для определения типов наблюдаемых.

Sr.No. Функция
1

ko.isComputed

Возврат true если свойство Computed Observable.

2

ko.isObservable

Возврат true если свойство - Observable, Observable array или Computed Observable.

3

ko.isWritableObservable

Возврат trueif Observable, Observable array или Writable Computed Observable. (Это также называется ko.isWriteableObservable)

Записываемые вычисляемые наблюдаемые

Computed Observable является производным от одного или нескольких других Observable, поэтому он доступен только для чтения. Однако возможно, что можно сделать Computed Observable доступным для записи. Для этого вам необходимо предоставить функцию обратного вызова, которая работает с записанными значениями.

Эти доступные для записи Computed Observables работают так же, как и обычные Observables. Кроме того, они требуют создания настраиваемой логики для вмешательства в действия чтения и записи.

Можно присвоить значения многим свойствам Observables или Computed Observable, используя следующий синтаксис цепочки.

myViewModel.fullName('Tom Smith').age(45)

пример

В следующем примере демонстрируется использование Writable Computable Observable.

<!DOCTYPE html>
   <head >
      <title>KnockoutJS Writable Computed Observable</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"></script>
   </head>

   <body>
      <p>Enter your birth Date: <input type = "date" data-bind = "value: rawDate" ></p>
      <p><span data-bind = "text: yourAge"></span></p>

      <script>
         function MyViewModel() {
            this.yourAge = ko.observable();
            today = new Date();
            rawDate = ko.observable();

            this.rawDate = ko.pureComputed ({

               read: function() {
                  return this.yourAge;
               },

               write: function(value) {
                  var b = Date.parse(value);    // convert birth date into milliseconds
                  var t = Date.parse(today);    // convert todays date into milliseconds
                  diff = t - b;                 // take difference
                  var y = Math.floor(diff/31449600000);     // difference is converted
                                                            // into years. 31449600000
                                                            //milliseconds form a year.

                  var m = Math.floor((diff % 31449600000)/604800000/4.3);  // calculating
                                                                           // months.
                                                                           // 604800000
                                                                           // milliseconds
                                                                           // form a week.

                  this.yourAge("You are " + y + " year(s) " + m +" months old.");
               },
               owner: this
            });
         }

         ko.applyBindings(new MyViewModel());
      </script>

   </body>
</html>

В приведенном выше коде rawDate - это свойство pureComputed, принимаемое из пользовательского интерфейса. yourAge Наблюдаемое происходит от rawDate.

Даты в JavaScript обрабатываются в миллисекундах. Следовательно, обе даты (сегодняшняя дата и дата рождения) конвертируются в миллисекунды, а затем разница между ними конвертируется обратно в годы и месяцы.

Вывод

Давайте выполним следующие шаги, чтобы увидеть, как работает приведенный выше код -

  • Сохраните приведенный выше код в writable_computed_observable.htm файл.

  • Откройте этот HTML-файл в браузере.

  • Введите любую дату рождения и наблюдайте, что возраст рассчитывается.

Декларативная привязка в KnockoutJS обеспечивает мощный способ подключения данных к пользовательскому интерфейсу.

Важно понимать взаимосвязь между привязками и Observables. Технически эти двое разные. Вы можете использовать обычный объект JavaScript, поскольку ViewModel и KnockoutJS могут правильно обрабатывать привязку View.

Без Observable свойство из пользовательского интерфейса будет обрабатываться только в первый раз. В этом случае он не может обновляться автоматически на основе обновления базовых данных. Для этого привязки должны быть отнесены к наблюдаемым свойствам.

Синтаксис привязки

Переплет состоит из 2 предметов, переплет name и value. Ниже приводится простой пример -

Today is : <span data-bind = "text: whatDay"></span>

Здесь текст - это имя привязки, а whatDay - значение привязки. Вы можете иметь несколько привязок, разделенных запятой, как показано в следующем синтаксисе.

Your name: <input data-bind = "value: yourName, valueUpdate: 'afterkeydown'" />

Здесь значение обновляется после нажатия каждой клавиши.

Обязательные значения

Значение привязки может быть single value, literal, а variable или может быть JavaScriptвыражение. Если привязка относится к некоторому недопустимому выражению или ссылке, то KO выдаст ошибку и прекратит обработку привязки.

Ниже приведены несколько примеров привязок.

<!-- simple text binding -->
<p>Enter employee name: <input   -bind = 'value: empName' /></p>

<!-- click binding, call a specific function -->
<button data-bind="click: sortEmpArray">Sort Array</button>

<!-- options binding -->
<select multiple = "true" size = "8" data-bind = "options: empArray , 
   selectedOptions: chosenItem"> </select>

Обратите внимание на следующие моменты -

  • Пробелы не имеют никакого значения.

  • Начиная с KO 3.0, вы можете пропустить значение привязки, которое даст привязке неопределенное значение.

Контекст привязки

На данные, которые используются в текущих привязках, может ссылаться объект. Этот объект называетсяbinding context.

Иерархия контекста создается и управляется KnockoutJS автоматически. В следующей таблице перечислены различные типы контекстов привязки, предоставляемые KO.

Sr.No. Типы и описание контекста привязки
1

$root

Это всегда относится к ViewModel верхнего уровня. Это позволяет получить доступ к методам верхнего уровня для управления ViewModel. Обычно это объект, который передается в ko.applyBindings.

2

$data

Это свойство очень похоже на thisключевое слово в объекте Javascript. Свойство $ data в контексте привязки относится к объекту ViewModel для текущего контекста.

3

$index

Это свойство содержит индекс текущего элемента массива внутри цикла foreach. Значение $ index будет изменяться автоматически при обновлении базового массива Observable. Очевидно, что этот контекст доступен только дляforeach привязки.

4

$parent

Это свойство относится к родительскому объекту ViewModel. Это полезно, когда вы хотите получить доступ к внешним свойствам ViewModel изнутри вложенного цикла.

5

$parentContext

Объект контекста, связанный на родительском уровне, называется $parentContext. Это отличается от$parent. $ parent относится к данным. Принимая во внимание, что $ parentContext относится к контексту привязки. Например, вам может потребоваться доступ к индексу внешнего элемента foreach из внутреннего контекста.

6

$rawdata

Этот контекст содержит необработанное значение ViewModel в текущей ситуации. Это похоже на$data but the difference is, if ViewModel is wrapped in Observable, then $данные просто разворачиваются. ViewModel и $ rawdata становятся фактическими наблюдаемыми данными.

7

$component

Этот контекст используется для ссылки на ViewModel этого компонента, когда вы находитесь внутри определенного компонента. Например, вы можете захотеть получить доступ к некоторому свойству из ViewModel вместо текущих данных в разделе шаблона компонента.

8

$componentTemplateNodes

Он представляет собой массив узлов DOM, передаваемых этому конкретному компоненту, когда вы находитесь в пределах определенного шаблона компонента.

Следующие термины также доступны в обязательном порядке, но не являются обязательным контекстом.

  • $context - Это не что иное, как существующий объект контекста привязки.

  • $element - Этот объект ссылается на элемент в DOM в текущей привязке.

Работа с текстом и внешним видом

Ниже приводится список типов привязки, предоставляемых KO для работы с текстом и визуальным оформлением.

Sr.No. Тип привязки и использование
1 visible: <условие-привязки>

Чтобы показать или скрыть элемент HTML DOM в зависимости от определенных условий.

2 текст: <значение-привязки>

Чтобы установить содержимое элемента HTML DOM.

3 html: <значение-привязки>

Чтобы установить содержимое разметки HTML для элемента DOM.

4 css: <объект-привязки>

Чтобы применить классы CSS к элементу.

5 стиль: <объект-привязки>

Чтобы определить встроенный атрибут стиля элемента.

6 attr: <объект-привязки>

Для динамического добавления атрибутов к элементу.

Работа с привязками потока управления

Ниже приведен список типов привязки потока управления, предоставленный KO.

Sr.No. Тип привязки и использование
1 foreach: <массив-привязок>

В этой привязке каждый элемент массива упоминается в разметке HTML в цикле.

2 если: <условие-привязки>

Если условие истинно, то будет обработана данная разметка HTML. В противном случае он будет удален из DOM.

3 если не: <условие-привязки>

Отрицание If. Если условие истинно, то будет обработана данная разметка HTML. В противном случае он будет удален из DOM.

4 с: <объект-привязки>

Эта привязка используется для привязки дочерних элементов объекта в контексте указанного объекта.

5 компонент: <имя-компонента> ИЛИ компонент: <объект-компонента>

Эта привязка используется для вставки компонента в элементы DOM и необязательной передачи параметров.

Работа с привязками полей формы

Ниже приведен список типов привязки полей формы, предоставляемых KO.

Sr.No. Тип привязки и использование
1 щелкните: <функция привязки>

Эта привязка используется для вызова функции JavaScript, связанной с элементом DOM, на основе щелчка.

2 событие:

Эта привязка используется для прослушивания указанных событий DOM и вызова связанных с ними функций-обработчиков на их основе.

3 отправить: <функция привязки>

Эта привязка используется для вызова функции JavaScript при отправке связанного элемента DOM.

4 включить: <значение-привязки>

Эта привязка используется для включения определенных элементов DOM на основе указанного условия.

5 отключить: <значение-привязки>

Эта привязка отключает связанный элемент DOM, если значение параметра истинно.

6 значение: <значение-привязки>

Эта привязка используется для привязки значения соответствующего элемента DOM к свойству ViewModel.

7 textInput: <значение-привязки>

Эта привязка используется для создания двусторонней привязки между текстовым полем или текстовым полем и свойством ViewModel.

8 hasFocus: <значение-привязки>

Эта привязка используется для ручной установки фокуса элемента HTML DOM через свойство ViewModel.

9 проверено: <значение-привязки>

Эта привязка используется для создания связи между проверяемым элементом формы и свойством ViewModel.

10 параметры: <массив-привязки>

Эта привязка используется для определения параметров для элемента выбора.

11 selectedOptions: <массив-привязок>

Эта привязка используется для работы с элементами, которые выбраны в данный момент в элементе управления формой выбора из нескольких списков.

12 uniqueName: <значение-привязки>

Эта привязка используется для создания уникального имени для элемента DOM.

KnockoutJs автоматически отслеживает зависимости при обновлении значений. У него есть единственный объект под названиемdependency tracker (ko.dependencyDetection), который действует как посредник между двумя сторонами для подписки на зависимости.

Ниже приводится алгоритм отслеживания зависимостей.

Step 1 - Каждый раз, когда вы объявляете вычисляемую наблюдаемую, KO немедленно вызывает свою функцию оценщика, чтобы получить ее начальное значение.

Step 2- Подписка устанавливается на любой наблюдаемый объект, который читает оценщик. В приложении старые подписки, которые больше не используются, удаляются.

Step 3 - KO, наконец, уведомляет обновленную вычисленную наблюдаемую.

Example

<!DOCTYPE html>
<html>
   <head>
      <title>KnockoutJS How Dependency Tracking Works</title>
      <!-- CDN's-->
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js"
         type = "text/javascript"></script>
   </head>
   
   <body>
      <div>
         <form data-bind = "submit: addFruits">
            <b>Add Fruits:</b>
            <input data-bind = 'value: fruitToAdd, valueUpdate: "afterkeydown"'/>
            <button type = "submit" data-bind = "enable: fruitToAdd().length > 0">Add</button>
            <p><b>Your fruits list:</b></p>
            <select multiple = "multiple" width = "50" data-bind = "options: fruits"> </select>
         </form>
      </div>
      
      <script>
         var Addfruit = function(fruits) {
            this.fruits = ko.observableArray(fruits);
            this.fruitToAdd = ko.observable("");
            
            this.addFruits = function() {
               
               if (this.fruitToAdd() != "") {
                  this.fruits.push(this.fruitToAdd());   // Adds a fruit
                  this.fruitToAdd("");                   // Clears the text box
               }
                
            }.bind(this);                                // "this" is the view model
         };

         ko.applyBindings(new Addfruit(["Apple", "Orange", "Banana"]));
      </script>
      
   </body>
</html>

Output

Давайте выполним следующие шаги, чтобы увидеть, как работает приведенный выше код -

  • Сохраните приведенный выше код в dependency_tracking.htm файл.

  • Откройте этот HTML-файл в браузере.

  • Введите любое название фрукта и нажмите кнопку «Добавить».

Управление зависимостями с помощью Peek

Доступ к вычисляемому наблюдаемому можно получить без создания зависимости, используя peekфункция. Он управляет Observable, обновляя вычисляемое свойство.

Example

<!DOCTYPE html>
<html>
   <head>
      <title>KnockoutJs Controlling Dependencies Using Peek</title>
      <!-- CDN's-->
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js"
         type = "text/javascript"></script>
   </head>
   
   <body>
      <div class = "logblock">
         <h3>Computed Log</h3>
         <pre class = "log" data-bind = "html: computedLog"></pre>
      </div>

      <script>
         function AppData() {
            this.firstName = ko.observable('John');
            this.lastName = ko.observable('Burns');
            this.computedLog = ko.observable('Log: ');
            
            this.fullName = ko.computed(function () {
               var value = this.firstName() + " " + this.lastName();
               this.computedLog(this.computedLog.peek() + value + '; <br/>');
               return value;
            }, this);

            this.step = ko.observable(0);
            this.next = function () {
               this.step(this.step() === 2 ? 0 : this.step()+1);
            };
         };
         
         ko.applyBindings(new AppData());
      </script>
      
   </body>
</html>

Output

Давайте выполним следующие шаги, чтобы увидеть, как работает приведенный выше код -

  • Сохраните приведенный выше код в dependency_tracking_peek.htm файл.

  • Откройте этот HTML-файл в браузере.

Наблюдения

Игнорирование зависимостей в вычисленной зависимости

В ko.ignoreDependenciesФункция помогает игнорировать те зависимости, которые вы не хотите отслеживать в вычисленных зависимостях. Ниже приводится его синтаксис.

ko.ignoreDependencies( callback, callbackTarget, callbackArgs );

Почему круговые зависимости не имеют смысла

Если KO оценивает Computed Observable, он не будет перезапускать оценку зависимого Computed Observable. Следовательно, нет смысла включать циклы в цепочки зависимостей.

Templateпредставляет собой набор элементов DOM, которые можно использовать повторно. Шаблоны упрощают создание сложных приложений благодаря свойству минимизировать дублирование элементов DOM.

Есть 2 способа создания шаблонов.

  • Native templating- Этот метод поддерживает привязки потока управления, такие как foreach, with и if. Эти привязки захватывают разметку HTML, существующую в элементе, и используют ее в качестве шаблона для случайных элементов. Для этого шаблона не требуется никакой внешней библиотеки.

  • String-based templating- KO подключается к стороннему движку для передачи в него значений ViewModel и вставляет полученную разметку в документ. Например, JQuery.tmpl и Underscore Engine.

Syntax

template: <parameter-value>

<script type = "text/html" id = "template-name">
   ...
   ...   // DOM elemets to be processed
   ...
</script>

Обратите внимание, что type предоставляется как text/html в блоке сценария, чтобы уведомить KO о том, что это не исполняемый блок, а просто блок шаблона, который необходимо отобразить.

Parameters

Комбинация следующих свойств может быть отправлена ​​как значение параметра в шаблон.

  • name - Это представляет собой имя шаблона.

  • nodes- Это представляет собой массив узлов DOM, который будет использоваться в качестве шаблона. Этот параметр игнорируется, если передается параметр имени.

  • data - Это не что иное, как данные, которые будут отображаться через шаблон.

  • if - Шаблон будет обслуживаться, если данное условие приводит к истинному или истинному значению.

  • foreach - Для обслуживания шаблона в формате foreach.

  • as - Это просто для создания псевдонима в элементе foreach.

  • afterAdd, afterRender, beforeRemove - Все они предназначены для представления вызываемых функций, которые должны выполняться в зависимости от выполняемой операции.

Наблюдения

Визуализация именованного шаблона

Шаблоны неявно определяются разметкой HTML внутри DOM при использовании с привязками потока управления. Однако при желании вы можете выделить шаблоны в отдельный элемент, а затем ссылаться на них по имени.

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - Named Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
   </head>

   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <div data-bind = "template: { name: 'friend-template', data: friend1 }"></div>
      <div data-bind = "template: { name: 'friend-template', data: friend2 }"></div>

      <script type = "text/html" id = "friend-template">
         <h3 data-bind = "text: name"></h3>
         <p>Contact Number: <span data-bind = "text: contactNumber"></span></p>
         <p>Email-id: <span data-bind = "text: email"></span></p>
      </script>

      <script type = "text/javascript">
         function MyViewModel() {
            this.friend1 = { 
               name: 'Smith', 
               contactNumber: 4556750345, 
               email: '[email protected]' 
            };
            
            this.friend2 = { 
               name: 'Jack', 
               contactNumber: 6789358001, 
               email: '[email protected]' 
            };
         }

         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
      
   </body>
</html>

Output

Давайте выполним следующие шаги, чтобы увидеть, как работает приведенный выше код -

  • Сохраните приведенный выше код в template-named.htm файл.

  • Откройте этот HTML-файл в браузере.

  • Здесь шаблон друга используется 2 раза.

Использование "foreach" в шаблоне

Ниже приводится пример использования foreach параметр вместе с именем шаблона.

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - foreach used with Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
   </head>

   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <div data-bind = "template: { name: 'friend-template', foreach: friends }"></div>

      <script type = "text/html" id = "friend-template">
         <h3 data-bind = "text: name"></h3>
         <p>Contact Number: <span data-bind = "text: contactNumber"></span></p>
         <p>Email-id: <span data-bind = "text: email"></span></p>
      </script>

      <script type = "text/javascript">
         function MyViewModel() {
            this.friends = [
               { name: 'Smith', contactNumber: 4556750345, email: '[email protected]' },
               { name: 'Jack', contactNumber: 6789358001, email: '[email protected]' },
               { name: 'Lisa', contactNumber: 4567893131, email: '[email protected]' }
            ]
         }

         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
      
   </body>
</html>

Output

Давайте выполним следующие шаги, чтобы увидеть, как работает приведенный выше код -

  • Сохраните приведенный выше код в template-foreach.htm файл.

  • Откройте этот HTML-файл в браузере.

  • Здесь элемент управления foreach используется в привязке шаблона.

Создание псевдонима с использованием ключевого слова для элементов foreach

Ниже показано, как можно создать псевдоним для элемента foreach.

<div data-bind = "template: { 
   name: 'friend-template', 
   foreach: friends, 
   as: 'frnz' 
}"></div>

Становится легко ссылаться на родительские объекты изнутри циклов foreach, создавая псевдоним. Эта функция полезна, когда код сложный и многоуровневый.

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - using alias in Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
   </head>

   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <ul data-bind = "template: { 
         name: 'friend-template', 
         foreach: friends, 
         as: 'frnz' 
      }"></ul>

      <script type = "text/html" id = "friend-template">
         <li>
            <h3 data-bind = "text: name"></h3>
            <span>Contact Numbers</span>
            <ul data-bind = "template: { 
               name : 'contacts-template', 
               foreach:contactNumber, 
               as: 'cont'
            } "></ul>
            <p>Email-id: <span data-bind = "text: email"></span></p>
         </li>
      </script>

      <script type = "text/html" id = "contacts-template">
         <li>
            <p><span data-bind = "text: cont"></span></p>
         </li>
      </script>

      <script type = "text/javascript">
         function MyViewModel() {
            this.friends = ko.observableArray ( [
               { 
                  name: 'Smith', 
                  contactNumber: [ 4556750345, 4356787934 ], 
                  email: '[email protected]' 
               },
               
               { 
                  name: 'Jack', 
                  contactNumber: [ 6789358001, 3456895445 ], 
                  email: '[email protected]' 
               },
               
               { 
                  name: 'Lisa', 
                  contactNumber: [ 4567893131, 9876456783, 1349873445 ],  
                  email: '[email protected]' 
               }
            ]);
         }

         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
      
   </body>
</html>

Output

Давайте выполним следующие шаги, чтобы увидеть, как работает приведенный выше код -

  • Сохраните приведенный выше код в template-as-alias.htm файл.

  • Откройте этот HTML-файл в браузере.

  • Вместо полного имени массивов используется псевдоним.

Использование afterAdd, beforeRemove и afterRender

Бывают ситуации, когда необходимо запустить дополнительную настраиваемую логику для элементов DOM, созданных шаблоном. В таком случае можно использовать следующие обратные вызовы. Учтите, что вы используете элемент foreach, тогда -

afterAdd - Эта функция вызывается, когда новый элемент добавляется в массив, упомянутый в foreach.

beforeRemove - Эта функция вызывается непосредственно перед удалением элемента из массива, упомянутого в foreach.

afterRender - Упомянутая здесь функция вызывается каждый раз при рендеринге foreach и добавлении новых записей в массив.

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - Use of afterRender Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
      <script src = "https://code.jquery.com/jquery-2.1.3.min.js"
         type = "text/javascript"></script>
   </head>

   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <div data-bind = "template: { 
         name: 'friend-template', 
         foreach: friends , 
         afterRender: afterProcess
      }"></div>

      <script type = "text/html" id = "friend-template">
         <h3 data-bind = "text: name"></h3>
         <p>Contact Number: <span data-bind = "text: contactNumber"></span></p>
         <p>Email-id: <span data-bind = "text: email"></span></p>
         <button data-bind = "click: $root.removeContact">remove </button>
      </script>

      <script type = "text/javascript">
         function MyViewModel() {
            self = this;
            this.friends = ko.observableArray ([
               { name: 'Smith', contactNumber: 4556750345, email: '[email protected]' },
               { name: 'Jack', contactNumber: 6789358001, email: '[email protected]' },
            ])

            this.afterProcess = function(elements, data){
               $(elements).css({color: 'magenta' });
            }

            self.removeContact = function() {
               self.friends.remove(this);
            }
         }

         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
   </body>
</html>

Output

Давайте выполним следующие шаги, чтобы увидеть, как работает приведенный выше код -

  • Сохраните приведенный выше код в template-afterrender.htm файл.

  • Откройте этот HTML-файл в браузере.

  • Здесь функция afterProcess выполняется каждый раз при отрисовке foreach.

Выбор шаблона динамически

Если доступно несколько шаблонов, их можно выбрать динамически, задав имя как observableпараметр. Следовательно, значение шаблона будет повторно оцениваться при изменении параметра имени и, в свою очередь, данные будут повторно отображаться.

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - Dynamic Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
   </head>
   
   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <div data-bind = "template: { 
         name: whichTemplate, 
         foreach: friends 
      }"></div>

      <script type = "text/html" id = "only-phon">
         <h3 data-bind = "text: name"></h3>
         <p>Contact Number: <span data-bind = "text: contactNumber"></span></p>
      </script>

      <script type = "text/html" id = "only-email">
         <h3 data-bind = "text: name"></h3>
         <p>Email-id: <span data-bind = "text: email"></span></p>
      </script>

      <script type = "text/javascript">
         function MyViewModel() {
   
            this.friends = ko.observableArray ([
               {
                  name: 'Smith', 
                  contactNumber: 4556750345, 
                  email: '[email protected]', 
                  active: ko.observable(true)
               },
               
               {
                  name: 'Jack', 
                  contactNumber: 6789358001, 
                  email: '[email protected]', 
                  active: ko.observable(false)
               },
            ]);

            this.whichTemplate = function(friends) {
               return friends.active() ? "only-phon" : "only-email";
            }
         }

         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
      
   </body>
</html>

Output

Давайте выполним следующие шаги, чтобы увидеть, как работает приведенный выше код -

  • Сохраните приведенный выше код в template-dynamic.htm файл.

  • Откройте этот HTML-файл в браузере.

  • Используемый шаблон выбирается в зависимости от активного значения флага.

Использование внешних строковых движков

Собственные шаблоны отлично работают с различными элементами потока управления даже с вложенными блоками кода. KO также предлагает способ интеграции с внешней библиотекой шаблонов, такой как Underscore templating Engine или JQuery.tmpl.

Как упоминалось на официальном сайте, JQuery.tmpl больше не находится в активной разработке с декабря 2011 года. Следовательно, использование собственных шаблонов KO рекомендуется только вместо JQuery.tmpl или любого другого механизма шаблонов на основе строк.

Пожалуйста, обратитесь к официальному сайту для получения более подробной информации.

Компоненты - отличный способ организации кода пользовательского интерфейса для структурирования большого приложения и обеспечения возможности повторного использования кода.

Он унаследован или вложен от другого компонента. Для загрузки и настройки он определяет свои собственные соглашения или логику.

Он упакован для повторного использования в приложении или проекте. Представляет полные разделы приложения или небольшие элементы управления / виджеты. Он может быть загружен или предварительно загружен по запросу.

Регистрация компонентов

Компоненты могут регистрироваться с помощью ko.components.register()API. Это помогает загружать и представлять компоненты в KO. Для регистрации ожидается название компонента с конфигурацией. В конфигурации указывается, как определить модель представления и шаблон.

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- Компоненты можно использовать без использования дополнительного элемента контейнера. Это можно сделать с помощьюcontainerless flow элемент управления, аналогичный тегу комментария.

<!--ko.component: ""-->
<!--/ko-->

Пользовательский элемент

Пользовательский элемент - это способ визуализации компонента. Здесь вы можете напрямую написать самоописательное имя элемента разметки, вместо того, чтобы определять заполнитель, через который компоненты связываются.

<products-list params = "name: userName, type: userType"></products-list>

Переданный параметр

paramsАтрибут используется для передачи параметра компоненту viewModel. Он похож на атрибут привязки данных. Содержимое атрибута params интерпретируется как литерал объекта JavaScript (точно так же, как атрибут привязки данных), поэтому вы можете передавать произвольные значения любого типа. Он может передавать параметр следующими способами -

  • Communication between parent and child components- Компонент не создается сам по себе, поэтому на свойства модели просмотра ссылаются извне компонента и, таким образом, они будут получены моделью просмотра дочернего компонента. Например, в следующем синтаксисе вы можете увидеть, чтоModelValue является родительской моделью представления, которую получает конструктор дочерней модели представления ModelProperty.

  • Passing observable expressions - Имеет три значения в параметре params.

    • simpleExpression- Это числовое значение. Он не включает никаких наблюдаемых.

    • simpleObservable- Это экземпляр, определенный в родительской модели viewModel. Родительский viewModel автоматически получит изменения наблюдаемого, сделанные дочерним viewModel.

    • observableExpression- Expression читает наблюдаемое, когда выражение вычисляется само по себе. Когда наблюдаемое значение изменяется, результат выражения также может меняться со временем.

Мы можем передать параметры следующим образом -

<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-файл в браузере.

Загрузчики компонентов

Загрузчики компонентов используются для асинхронной передачи пары шаблон / модель представления для заданного имени компонента.

Загрузчик компонентов по умолчанию

Загрузчик компонентов по умолчанию зависит от явно зарегистрированной конфигурации. Каждый компонент регистрируется перед использованием компонента.

ko.components.defaultLoader

Функции утилиты загрузчика компонентов

Загрузчик компонентов по умолчанию может читать и писать, используя следующие функции.

Sr.No. Служебные функции и описание
1

ko.components.register(name, configuration)

Компонент зарегистрирован.

2

ko.components.isRegistered(name)

Если конкретное имя компонента уже зарегистрировано, оно возвращается как истина, иначе ложь.

3

ko.components.unregister(name)

Название компонента удаляется из реестра.

4

ko.components.get(name, callback)

Эта функция по очереди обращается к каждому зарегистрированному загрузчику, чтобы определить, кто первым передал определение viewModel / template для имени компонента. Затем он возвращает объявление viewModel / template, вызываяcallback. Если зарегистрированный загрузчик ничего не может найти о компоненте, он вызываетcallback(null).

5

ko.components.clearCachedDefinition(name)

Эта функция может быть вызвана, когда мы хотим очистить данную запись в кэше компонента. Если компонент понадобится в следующий раз, снова обратятся к загрузчикам.

Реализация пользовательского загрузчика компонентов

Загрузчик пользовательских компонентов может быть реализован следующими способами:

  • getConfig(name, callback)- В зависимости от названий мы можем передавать конфигурации программно. Мы можем вызвать обратный вызов (componentConfig) для передачи конфигураций, где объект componentConfig может использоваться loadComponent или любым другим загрузчиком.

  • loadComponent(name, componentConfig, callback)- Эта функция разрешает viewModel и часть шаблона конфигурации в зависимости от того, как она настроена. Мы можем вызвать обратный вызов (результат) для передачи пары 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 с использованием настраиваемой логики.