简体   繁体   English

Knockout Google Map:组件与自定义绑定处理程序

[英]Knockout Google Map: Component vs. Custom Binding Handler

When I google " Knockout Google Maps " I find quite some KO-based Google Maps implementations.当我用谷歌搜索“ Knockout Google Maps ”时,我发现了很多基于 KO 的 Google Maps 实现。 All of which I was able to find take the approach to use a custom binding handler whereas I originally intended to implement it as a Knockout component.我能够找到的所有这些都采用了使用自定义绑定处理程序的方法,而我最初打算将其实现为 Knockout 组件。

Examples:例子:

Can anyone point me in the right direction why one would prefer a custom binding handler over a KO component here ?任何人都可以指出正确的方向,为什么人们更喜欢这里的自定义绑定处理程序而不是 KO 组件

My planned use case is this:我计划的用例是这样的:

I'm implementing a page with a list of address search results.我正在实现一个包含地址搜索结果列表的页面。 The list so far is a KO component, each list entry is generated by another KO component which the list component repeatedly calls in a foreach binding.到目前为止,列表是一个 KO 组件,每个列表条目都由另一个 KO 组件生成,列表组件在 foreach 绑定中重复调用该组件。 Next to this list of search results I need a google map showing the result entries also in the map.在这个搜索结果列表旁边,我需要一个谷歌地图,在地图中显示结果条目。 There will also be quite a lot of interaction between the list, the list entries and the map.列表、列表条目和地图之间也会有相当多的交互。

Here's what I've got so far:这是我到目前为止所得到的:

 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>

A component and a custom handler are completely different things.组件和自定义处理程序是完全不同的东西。

Custom binding自定义绑定

Basically a custom binding have access to:基本上自定义绑定可以访问:

  • the HTML component where it's used使用它的 HTML 组件
  • the bound value (expression supplied to the binding)绑定值(提供给绑定的表达式)
  • all the other bindings in the element元素中的所有其他绑定
  • the binding context of the element, from which you can acces to $root , $parent , and so on元素的绑定上下文,您可以从中访问$root$parent

Its definition includes two functions:它的定义包括两个函数:

  • init : that allows to do the initial setup, like initializing widgets, setting event handlers and so on init :允许进行初始设置,如初始化小部件、设置事件处理程序等
  • update : it's called after init . update :它在init之后调用。 In that moment you can access properties (including observable properties) through the binding, all the element bindings, the context and so on.在那一刻,您可以通过绑定、所有元素绑定、上下文等访问属性(包括可观察的属性)。 This creates subscriptios that will call update when any of the accessed observable changes.这将创建 subscriptios,当任何访问的 observable 发生变化时,它会调用 update。

So a custom binding shuld be used when you need to interact directly with the DOM element, for example to modify its properties, initialize widgets, subscribe to events and so on因此,当您需要直接与 DOM 元素交互时,应使用自定义绑定,例如修改其属性、初始化小部件、订阅事件等

Component零件

A component is completely different.一个组件是完全不同的。 When you define a componente you must define:定义组件时,您必须定义:

  • a template, which is a set of DOM elements, usually with bindings模板,它是一组 DOM 元素,通常带有绑定
  • a viewmodel (usually a constructor or a factory)视图模型(通常是构造函数或工厂)

When you use the component:当您使用该组件时:

  • the viewmodel is instanced视图模型被实例化
  • the template is loaded模板已加载
  • the viewmodel is bound to the template视图模型绑定到模板

So, a componente allows to reuse viewmodels and templates因此,组件允许重用视图模型和模板

So, what's the difference?那么,有什么区别呢?

A custom binding has direct access to the DOM elements, allowing to interact with them, subscribe to events, modify properties, and so on自定义绑定可以直接访问 DOM 元素,允许与它们交互、订阅事件、修改属性等

A component is only a viewmodel, and a set of DOM elements with bindings to that particular viewmodel.组件只是一个视图模型,以及一组绑定到该特定视图模型的 DOM 元素。

So, in the case of Google Maps, which needs to initialize a widget (the map) and interact with Map events, and respond to observable propèrties cahnges, you could never use a component, because the component doesn't allow the direct interaction with the DOM elements.因此,对于需要初始化小部件(地图)并与地图事件交互并响应可观察属性变化的 Google 地图,您永远不能使用组件,因为该组件不允许与DOM 元素。 (Remember is a bunch of HTML elements with bindings, and the corrresponding view model, whic can't include any logic to intercat with those elements). (记住是一堆带有绑定的 HTML 元素,以及相应的视图模型,不能包含任何与这些元素交互的逻辑)。

A custom binding usually applies to a single element (althoug it could handle its children, like foreach ).自定义绑定通常适用于单个元素(尽管它可以处理其子元素,如foreach )。 In the case of Google Maps you only need the element in which you'll show the map.对于 Google 地图,您只需要显示地图的元素。

A component is usually a more or less complex set of DOM elements, which are not accesible "from the outside".组件通常是一组或多或少复杂的 DOM 元素,“从外部”无法访问这些元素。 The only communication with the main viewmodel is done through parameters.与主视图模型的唯一通信是通过参数完成的。 The component cannot directly interact with the DOM elements: it must do it via ko bindings.组件不能直接与 DOM 元素交互:它必须通过 ko 绑定来实现。

So, for the case of Google Maps is clear that you need a custom binding.因此,对于 Google Maps 的情况,很明显您需要自定义绑定。

It only makes sense to create a component when you want to modularize or reuse a set of DOM elements, and the related viewmodel, which can also include functionality like accessing web services (via AJAX), making computations (propbaly by using computed observables), and so on.只有当你想模块化或重用一组 DOM 元素和相关的视图模型时,创建一个组件才有意义,它还可以包括访问 Web 服务(通过 AJAX)、进行计算(propbaly 通过使用计算的可观察对象)等功能,等等。 For example, a shopping cart could be implemented using a component, which would include:例如,可以使用一个组件来实现购物车,其中包括:

  • the DOM elements to show the items in the cart (probably an HTML table, and some controls)显示购物车中商品的 DOM 元素(可能是 HTML 表格和一些控件)
  • controls to modify the cart content (for example for deleting elements, or changing quantities)修改购物车内容的控件(例如删除元素或更改数量)
  • a viewmodel that show the total, the taxes and so on显示总数、税收等的视图模型
  • functionality to store the cart for later, or pay for it (which could be ajax calls to services)存储购物车以备后用或为其付款的功能(可以是对服务的 ajax 调用)

In this case the cart would have a viewmodel which would include the computed observables (to show the total and taxes), the functionality to remove items, or modify quantities, or store or pay, and so on.在这种情况下,购物车将有一个视图模型,其中包括计算的可观察值(以显示总计和税收)、删除项目或修改数量、存储或支付等的功能。 And a concrete set of DOM elements with bindings for this viewmodel, ie the HTML to show the cart and interact with it.以及一组具体的 DOM 元素,具有此视图模型的绑定,即用于显示购物车并与之交互的 HTML。

In the case of Google Maps a component could not be used without the help of a custom binding or with the hacky use of additional, non ko, scripts .在 Google 地图的情况下,如果没有自定义绑定的帮助或使用额外的非 ko 脚本的 hacky,则无法使用组件。

If you wanted to show a list of places beside a map, and modify that list, you could use a component, which would include a viewmodel with the list and related functionality, and a template including an element with the Google Maps custom binding.如果您想在地图旁边显示地点列表,并修改该列表,您可以使用一个组件,该组件将包含一个带有列表和相关功能的视图模型,以及一个包含带有 Google 地图自定义绑定的元素的模板。 That would make sense: viewmodel + several elements.这是有道理的:viewmodel + 几个元素。

Conclusion结论

This all means that a custom binding usually have a deep interaction with the bound DOM element, while a component has a higher level interaction with the elements, which must be done through bindings.这一切都意味着自定义绑定通常与绑定的 DOM 元素有深度交互,而组件与元素有更高级别的交互,这必须通过绑定来完成。

So, they play a role at a very different level.因此,它们在非常不同的层面上发挥着作用。 You cannot compare or interchange them.您无法比较或互换它们。

If you insist on doing so, you could create a beast of a binding which behaves like a component, becasue you have full control on the elements, and full acces to the view model, but that's harder to implement than a component.如果你坚持这样做,你可以创建一个行为像组件的绑定的野兽,因为你可以完全控制元素,并且可以完全访问视图模型,但这比组件更难实现。 And probably could do the other way round also in some esoteric way.并且可能也可以以某种深奥的方式反过来做。

Binding捆绑

Binding , a custom or not, is a very simple concept that covers 2 things:绑定,无论是否是自定义的,都是一个非常简单的概念,涵盖两件事:

  1. A property of a UI element changes, and thus it should update an object (ViewModel) UI 元素的属性发生变化,因此它应该更新对象 (ViewModel)
  2. A property of the object (ViewModel) changes, and thus it should update the UI element.对象 (ViewModel) 的属性发生变化,因此它应该更新 UI 元素。

From the above if only 1 implemented, it is called One Way Binding (because if you change the UI, it will update the object but not the other way around).从上面如果只实现了 1,它被称为单向绑定(因为如果你改变 UI,它会更新对象而不是相反)。 If both 1 and 2 are implemented, it is called Two Way Binding .如果 1 和 2 都实现了,则称为Two Way Binding

So at any time if you think you need something to do that, you would need to use binding, custom binding if the framework does not have the binding you need.所以在任何时候,如果你认为你需要做些什么,你就需要使用绑定,如果框架没有你需要的绑定,你就需要自定义绑定。

Most likely, the maps you speak of needed something like above.最有可能的是,你所说的地图需要像上面这样的东西。 And it actually did because the author says this in the first paragraph:它确实做到了,因为作者在第一段中这样说:

Concretely, you can learn how to make the maps marker part of the View and automatically change its position any time when the ViewModel behind changes.具体来说,你可以学习如何使地图标记成为视图的一部分,并在后面的 ViewModel 发生变化时自动更改其位置。

See, the author talks about 2 above: When the ViewModel changes, change the position of UI element.看,作者在上面讲了2:当ViewModel改变时,改变UI元素的位置。

Component零件

A component is a concept of having a reusable item that may have a UI but not necessarily, and all the code needed to make it work packaged along with it.组件是一个概念,即拥有一个可重用的项目,该项目可能具有 UI,但不一定具有 UI,并且使其工作所需的所有代码都打包在一起。 This way it can be reused.这样它就可以重复使用。 For example, it may simply be an input UI element that only allows numbers.例如,它可能只是一个只允许输入数字的输入 UI 元素。 All the code needed for it is packaged along with the UI element.它所需的所有代码都与 UI 元素一起打包。

Now the code packaged along with it may code related to bindings.现在与它一起打包的代码可能与绑定相关的代码。 It may even have custom bindings if the framework they used did not have the binding they needed.如果他们使用的框架没有他们需要的绑定,它甚至可能有自定义绑定。 In addition it may have additional code that has nothing to do with binding.此外,它可能还有与绑定无关的附加代码。

Furthermore, a component may have a single UI element or multiple.此外,一个组件可能有一个或多个 UI 元素。 A good example of a component with multiple elements would be a message box.具有多个元素的组件的一个很好的例子是消息框。

In Conclusion综上所述

Bindings and Components are separate things.绑定和组件是不同的东西。 A component may have bindings within it or it may have other code to make it work or both.一个组件可能在其中有绑定,或者它可能有其他代码来使其工作,或者两者兼而有之。

In the case of the maps you speak of, they have only added a feature to it: To react to changes in the ViewModel.对于您所说的地图,它们只添加了一个功能:对 ViewModel 中的变化做出反应。 It is not a component because it is not self contained and reusable.它不是一个组件,因为它不是独立的和可重用的。

They could have done it using a component.他们本可以使用组件来完成。 However, if they did that and said it is a KO component, it may still have KO specific binding code packaged with it along with the ViewModel and all the UI elements needed.然而,如果他们这样做并说它是一个 KO 组件,它可能仍然有 KO 特定的绑定代码与它一起打包,以及 ViewModel 和所有需要的 UI 元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM