Нокаут Google Map: компонент против пользовательского привязки

Когда я гуглю " Knockout Google Maps ", я нахожу довольно много основанных на KO реализаций Google Maps. Все, что я смог найти, использует подход, использующий пользовательский обработчик привязки, тогда как изначально я намеревался реализовать его как компонент Knockout.

Примеры:

Может ли кто-нибудь указать мне правильное направление, почему здесь предпочтительнее пользовательский обработчик привязки, а не компонент KO?

Мой запланированный вариант использования такой:

Я реализую страницу со списком результатов поиска адресов. Пока список является компонентом KO, каждая запись списка генерируется другим компонентом KO, который компонент списка неоднократно вызывает в привязке foreach. Рядом с этим списком результатов поиска мне нужна карта Google, показывающая записи результатов также на карте. Также будет довольно много взаимодействия между списком, записями списка и картой.

Вот что у меня так далеко:

var GMap = function () {
    var self = this;

    var initMap = function() {
        var map = new google.maps.Map(document.getElementById('map'), {
            zoom: 13,
            center: {lat: 51.4387974, lng: 6.9922915}
        });
    };
  
    initMap();
};
$(document).ready(function() {
  ko.components.register('gmap', {
    viewModel: GMap,
    template: { element: 'gmap' }
  });
  ko.applyBindings();
});
#map {
  height: 400px;
  width: 600px;
}
<script src="https://maps.googleapis.com/maps/api/js?v=3.22"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<gmap></gmap>
<template id="gmap">
  <div id="map"></div>
</template>

1 ответ

Компонент и пользовательский обработчик - это совершенно разные вещи.

Пользовательская привязка

По сути, пользовательские привязки имеют доступ к:

  • компонент HTML, где он используется
  • связанное значение (выражение, переданное привязке)
  • все остальные привязки в элементе
  • обязательный контекст элемента, из которого вы можете получить доступ к $root, $parent, и так далее

Его определение включает две функции:

  • init: это позволяет выполнить первоначальную настройку, например, инициализацию виджетов, настройку обработчиков событий и т. д.
  • update: это называется после init, В этот момент вы можете получить доступ к свойствам (включая наблюдаемые свойства) через привязку, все привязки элементов, контекст и так далее. Это создает подписчиков, которые будут вызывать обновление, когда любое из наблюдаемых изменений будет изменено.

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

Составная часть

Компонент совершенно другой. Когда вы определяете компонент, вы должны определить:

  • шаблон, представляющий собой набор элементов DOM, обычно с привязками
  • модель представления (обычно конструктор или фабрика)

Когда вы используете компонент:

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

Итак, компонент позволяет повторно использовать viewmodels и шаблоны

Так в чем же разница?

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

Компонент является только моделью представления и набором элементов DOM с привязками к этой конкретной модели представления.

Таким образом, в случае Google Maps, который должен инициализировать виджет (карту) и взаимодействовать с событиями карты, а также реагировать на наблюдаемые свойства, вы никогда не сможете использовать компонент, поскольку компонент не допускает прямого взаимодействия с элементы DOM. (Помните, это набор HTML-элементов с привязками и соответствующая модель представления, которая не может содержать никакой логики для взаимодействия с этими элементами).

Пользовательская привязка обычно применяется к одному элементу (хотя она может обрабатывать свои дочерние элементы, например, foreach). В случае Google Maps вам нужен только элемент, в котором вы будете показывать карту.

Компонент, как правило, представляет собой более или менее сложный набор элементов DOM, которые недоступны "извне". Единственная связь с основной моделью представления осуществляется через параметры. Компонент не может напрямую взаимодействовать с элементами DOM: он должен делать это посредством привязок ко.

Итак, для случая с Google Maps понятно, что вам нужна пользовательская привязка.

Создавать компонент имеет смысл только тогда, когда вы хотите модулировать или повторно использовать набор элементов DOM и связанную модель представления, которая также может включать такие функции, как доступ к веб-службам (через AJAX), выполнение вычислений (возможно, с использованием вычисляемых наблюдаемых), и так далее. Например, корзина покупок может быть реализована с использованием компонента, который будет включать:

  • элементы DOM для отображения товаров в корзине (возможно, HTML-таблица и некоторые элементы управления)
  • элементы управления для изменения содержимого корзины (например, для удаления элементов или изменения количества)
  • модель представления, которая показывает сумму, налоги и т. д.
  • функциональность для хранения корзины на потом или оплаты за нее (это могут быть вызовы ajax службам)

В этом случае корзина будет иметь модель представления, которая будет включать в себя вычисляемые наблюдаемые (для отображения суммы и налогов), функциональные возможности для удаления товаров, или изменения количества, или хранения или оплаты, и так далее. И конкретный набор элементов DOM с привязками для этой модели представления, т. Е. HTML для отображения корзины и взаимодействия с ней.

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

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

Заключение

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

Таким образом, они играют роль на совершенно другом уровне. Вы не можете сравнивать или обменивать их.

Если вы настаиваете на этом, вы можете создать зверя с привязкой, который будет вести себя как компонент, поскольку у вас есть полный контроль над элементами и полный доступ к модели представления, но это сложнее реализовать, чем компонент. И, вероятно, мог бы сделать и наоборот, эзотерически.

Привязка

Связывание, произвольное или нет, - очень простая концепция, охватывающая 2 вещи:

  1. Изменяется свойство элемента пользовательского интерфейса, поэтому он должен обновлять объект (ViewModel).
  2. Свойство объекта (ViewModel) изменяется, поэтому он должен обновлять элемент пользовательского интерфейса.

Из приведенного выше, если реализован только 1, он называется односторонним связыванием (потому что, если вы измените пользовательский интерфейс, он обновит объект, но не наоборот). Если реализованы и 1, и 2, это называется двусторонней привязкой.

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

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

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

Смотрите, автор говорит о 2 выше: при изменении ViewModel измените положение элемента пользовательского интерфейса.

Составная часть

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

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

Кроме того, компонент может иметь один или несколько элементов пользовательского интерфейса. Хорошим примером компонента с несколькими элементами может служить окно сообщения.

В заключении

Привязки и Компоненты - разные вещи. Компонент может иметь привязки внутри, или у него может быть другой код для его работы, или и то, и другое.

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

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

Другие вопросы по тегам