簡體   English   中英

Knockout Google Map:組件與自定義綁定處理程序

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

當我用谷歌搜索“ Knockout Google Maps ”時,我發現了很多基於 KO 的 Google Maps 實現。 我能夠找到的所有這些都采用了使用自定義綁定處理程序的方法,而我最初打算將其實現為 Knockout 組件。

例子:

任何人都可以指出正確的方向,為什么人們更喜歡這里的自定義綁定處理程序而不是 KO 組件

我計划的用例是這樣的:

我正在實現一個包含地址搜索結果列表的頁面。 到目前為止,列表是一個 KO 組件,每個列表條目都由另一個 KO 組件生成,列表組件在 foreach 綁定中重復調用該組件。 在這個搜索結果列表旁邊,我需要一個谷歌地圖,在地圖中顯示結果條目。 列表、列表條目和地圖之間也會有相當多的交互。

這是我到目前為止所得到的:

 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>

組件和自定義處理程序是完全不同的東西。

自定義綁定

基本上自定義綁定可以訪問:

  • 使用它的 HTML 組件
  • 綁定值(提供給綁定的表達式)
  • 元素中的所有其他綁定
  • 元素的綁定上下文,您可以從中訪問$root$parent

它的定義包括兩個函數:

  • init :允許進行初始設置,如初始化小部件、設置事件處理程序等
  • update :它在init之后調用。 在那一刻,您可以通過綁定、所有元素綁定、上下文等訪問屬性(包括可觀察的屬性)。 這將創建 subscriptios,當任何訪問的 observable 發生變化時,它會調用 update。

因此,當您需要直接與 DOM 元素交互時,應使用自定義綁定,例如修改其屬性、初始化小部件、訂閱事件等

零件

一個組件是完全不同的。 定義組件時,您必須定義:

  • 模板,它是一組 DOM 元素,通常帶有綁定
  • 視圖模型(通常是構造函數或工廠)

當您使用該組件時:

  • 視圖模型被實例化
  • 模板已加載
  • 視圖模型綁定到模板

因此,組件允許重用視圖模型和模板

那么,有什么區別呢?

自定義綁定可以直接訪問 DOM 元素,允許與它們交互、訂閱事件、修改屬性等

組件只是一個視圖模型,以及一組綁定到該特定視圖模型的 DOM 元素。

因此,對於需要初始化小部件(地圖)並與地圖事件交互並響應可觀察屬性變化的 Google 地圖,您永遠不能使用組件,因為該組件不允許與DOM 元素。 (記住是一堆帶有綁定的 HTML 元素,以及相應的視圖模型,不能包含任何與這些元素交互的邏輯)。

自定義綁定通常適用於單個元素(盡管它可以處理其子元素,如foreach )。 對於 Google 地圖,您只需要顯示地圖的元素。

組件通常是一組或多或少復雜的 DOM 元素,“從外部”無法訪問這些元素。 與主視圖模型的唯一通信是通過參數完成的。 組件不能直接與 DOM 元素交互:它必須通過 ko 綁定來實現。

因此,對於 Google Maps 的情況,很明顯您需要自定義綁定。

只有當你想模塊化或重用一組 DOM 元素和相關的視圖模型時,創建一個組件才有意義,它還可以包括訪問 Web 服務(通過 AJAX)、進行計算(propbaly 通過使用計算的可觀察對象)等功能,等等。 例如,可以使用一個組件來實現購物車,其中包括:

  • 顯示購物車中商品的 DOM 元素(可能是 HTML 表格和一些控件)
  • 修改購物車內容的控件(例如刪除元素或更改數量)
  • 顯示總數、稅收等的視圖模型
  • 存儲購物車以備后用或為其付款的功能(可以是對服務的 ajax 調用)

在這種情況下,購物車將有一個視圖模型,其中包括計算的可觀察值(以顯示總計和稅收)、刪除項目或修改數量、存儲或支付等的功能。 以及一組具體的 DOM 元素,具有此視圖模型的綁定,即用於顯示購物車並與之交互的 HTML。

在 Google 地圖的情況下,如果沒有自定義綁定的幫助或使用額外的非 ko 腳本的 hacky,則無法使用組件。

如果您想在地圖旁邊顯示地點列表,並修改該列表,您可以使用一個組件,該組件將包含一個帶有列表和相關功能的視圖模型,以及一個包含帶有 Google 地圖自定義綁定的元素的模板。 這是有道理的:viewmodel + 幾個元素。

結論

這一切都意味着自定義綁定通常與綁定的 DOM 元素有深度交互,而組件與元素有更高級別的交互,這必須通過綁定來完成。

因此,它們在非常不同的層面上發揮着作用。 您無法比較或互換它們。

如果你堅持這樣做,你可以創建一個行為像組件的綁定的野獸,因為你可以完全控制元素,並且可以完全訪問視圖模型,但這比組件更難實現。 並且可能也可以以某種深奧的方式反過來做。

捆綁

綁定,無論是否是自定義的,都是一個非常簡單的概念,涵蓋兩件事:

  1. UI 元素的屬性發生變化,因此它應該更新對象 (ViewModel)
  2. 對象 (ViewModel) 的屬性發生變化,因此它應該更新 UI 元素。

從上面如果只實現了 1,它被稱為單向綁定(因為如果你改變 UI,它會更新對象而不是相反)。 如果 1 和 2 都實現了,則稱為Two Way Binding

所以在任何時候,如果你認為你需要做些什么,你就需要使用綁定,如果框架沒有你需要的綁定,你就需要自定義綁定。

最有可能的是,你所說的地圖需要像上面這樣的東西。 它確實做到了,因為作者在第一段中這樣說:

具體來說,你可以學習如何使地圖標記成為視圖的一部分,並在后面的 ViewModel 發生變化時自動更改其位置。

看,作者在上面講了2:當ViewModel改變時,改變UI元素的位置。

零件

組件是一個概念,即擁有一個可重用的項目,該項目可能具有 UI,但不一定具有 UI,並且使其工作所需的所有代碼都打包在一起。 這樣它就可以重復使用。 例如,它可能只是一個只允許輸入數字的輸入 UI 元素。 它所需的所有代碼都與 UI 元素一起打包。

現在與它一起打包的代碼可能與綁定相關的代碼。 如果他們使用的框架沒有他們需要的綁定,它甚至可能有自定義綁定。 此外,它可能還有與綁定無關的附加代碼。

此外,一個組件可能有一個或多個 UI 元素。 具有多個元素的組件的一個很好的例子是消息框。

綜上所述

綁定和組件是不同的東西。 一個組件可能在其中有綁定,或者它可能有其他代碼來使其工作,或者兩者兼而有之。

對於您所說的地圖,它們只添加了一個功能:對 ViewModel 中的變化做出反應。 它不是一個組件,因為它不是獨立的和可重用的。

他們本可以使用組件來完成。 然而,如果他們這樣做並說它是一個 KO 組件,它可能仍然有 KO 特定的綁定代碼與它一起打包,以及 ViewModel 和所有需要的 UI 元素。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM