簡體   English   中英

Coffeescript類的行為不符合預期

[英]Coffeescript Class not Behaving as Expected

標題名稱錯誤,對不起。 不太確定如何對此進行總結。

我正在嘗試使用OpenLayers map API將帶有許多標記的地圖打印到頁面上。 我有可用的代碼,但是當我嘗試將其移至單獨的Coffeescript類時,它會靜默失敗。 以下代碼有效:

fromProjection = new OpenLayers.Projection("EPSG:4326") # Transform from WGS 1984
toProjection = new OpenLayers.Projection("EPSG:900913") # to Spherical Mercator Projection
mapnik = new OpenLayers.Layer.OSM()
markers = new OpenLayers.Layer.Markers("Markers")

map = new OpenLayers.Map("john-muir-trail-map")
markerCoordinates = -> $("\#john-muir-trail-data").data('markers').split('+')

paint = ->
  map.addLayer(mapnik)
  map.addLayer(markers)

  for pair in markerCoordinates()
    coords = pair.split(":")
    pos = new OpenLayers.LonLat(coords[1], coords[0]).transform( fromProjection, toProjection )
    markers.addMarker(new OpenLayers.Marker(pos))
    map.setCenter(pos, 8)


paint()

它依賴於兩個存在的div(一個ID為“ john-muir-trail-map”,另一個ID為“ john-muir-trail-data”和一些標記數據)。 當上面的代碼在我的主要.coffee文件中時,它工作得很好。

但是 ,當我嘗試通過將地圖代碼移到一個單獨的OpenLayerMap Coffeescript類中來對事物進行模塊化時,不會出現任何錯誤,但這是行不通的。 這就是我所做的。 (我很確定我正確地包含了這些東西。該類以及它的方法和屬性都可以從我的主文件中獲得):

class OpenLayersMap

  constructor: (mapId) ->
    @mapId = mapId

  fromProjection: new OpenLayers.Projection("EPSG:4326") # Transform from WGS 1984
  toProjection: new OpenLayers.Projection("EPSG:900913") # to Spherical Mercator Projection
  mapnik: new OpenLayers.Layer.OSM()
  markers: new OpenLayers.Layer.Markers("Markers")

  map: new OpenLayers.Map("#{@mapId}-map")
  markerCoordinates: -> $("\##{@mapId}-data").data('markers').split('+')

  paint: ->
    @map.addLayer(@mapnik)
    @map.addLayer(@markers)

    for pair in @markerCoordinates()
      coords = pair.split(":")
      pos = new OpenLayers.LonLat(coords[1], coords[0]).transform( @fromProjection, @toProjection )
      @markers.addMarker(new OpenLayers.Marker(pos))
      @map.setCenter(pos, 8)

window.OpenLayersMap = OpenLayersMap

然后,我在先前的文件中將其命名為:

map = new OpenLayersMap('john-muir-trail')
map.paint()

我認為OpenLayers圍繞投影等的細節並不重要。 重要的是, mapId正在傳入並正確使用,如果我將調試器扔到paint()函數中,則該調試器將被命中,並且那時所有可用的屬性對我來說都是很好的。 正確包含了該類,等等。 但是 ,沒有地圖被繪制。

我有Ruby背景,我想我對paint()函數的效果和副作用感到困惑。 如果它本質上是相同的行為,為什么在不同的文件中表現不同?

有任何想法為什么會失敗(無聲)? 它讓我有點發瘋。

我相信您在地圖屬性中使用@會導致此問題。 而不是訪問的當前實例的OpenLayersMap您呼叫的靜態屬性mapIdOpenLayersMap 例如:

map: new OpenLayers.Map("#{@mapId}-map")

將編譯為:

OpenLayersMap.prototype.map = new OpenLayers.Map("" + OpenLayersMap.mapId + "-map");

您將需要使map成為訪問構造函數中設置的@mapId的方法。

map: -> new OpenLayers.Map("#{@mapId}-map")

我完全同意Kyle Needham的解釋 ,但我想提出另一種解決方案。

要修復代碼,只需將map分配從類原型移至其構造函數:

class OpenLayersMap
  constructor: (mapId) ->
    @mapId = mapId
    @map = new OpenLayers.Map("#{@mapId}-map")

您還應該考慮從fromProjectiontoProjectionmapnikmarkers定義移至構造函數。

在您當前的實現中, OpenLayersMap所有實例將具有相同的markers值,例如:

l1 = new OpenLayersMap 'l1'
l2 = new OpenLayersMap 'l2'
l1.markers is l2.markers # true, meaning they are the same object

因此,通過l1.markers您不僅會影響OpenLayersMap類的所有現有實例,還將改變其原型。

這意味着,通過在OpenLayersMap類的任何實例中更改這四個屬性中的任何一個,您將對所有其他實例進行相同的更改。

如果所有這些類( ProjectionLayerMarkers )都是不可變的(即提供一堆幫助器,但是不保持任何狀態),那么您的實現是正確的,但是我懷疑有人會費心將一堆無狀態的幫助器包裝到類中。

因此,考慮將代碼更改為:

class OpenLayersMap
  constructor: (mapId) ->
    @mapId = mapId
    @map = new OpenLayers.Map "#{@mapId}-map"
    @fromProjection = new OpenLayers.Projection "EPSG:4326"
    @toProjection = new OpenLayers.Projection "EPSG:900913"
    @mapnik = new OpenLayers.Layer.OSM()
    @markers = new OpenLayers.Layer.Markers "Markers"

在這種情況下,每個OpenLayersMap實例將具有其自己的fromProjectiontoProjectionmapnikmarkers

暫無
暫無

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

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