简体   繁体   English

Coffeescript类的行为不符合预期

[英]Coffeescript Class not Behaving as Expected

Bad title name, sorry. 标题名称错误,对不起。 Not really sure how to summarize this. 不太确定如何对此进行总结。

I'm trying to use OpenLayers map API to print a map with a number of markers to a page. 我正在尝试使用OpenLayers map API将带有许多标记的地图打印到页面上。 I have working code, but when I try to move it into a separate Coffeescript class, it fails silently. 我有可用的代码,但是当我尝试将其移至单独的Coffeescript类时,它会静默失败。 The following code worked: 以下代码有效:

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()

It relies on two divs that exist (one with the id 'john-muir-trail-map' and another with the id 'john-muir-trail-data' and some marker data). 它依赖于两个存在的div(一个ID为“ john-muir-trail-map”,另一个ID为“ john-muir-trail-data”和一些标记数据)。 When the above code is in my main .coffee file, it works just great. 当上面的代码在我的主要.coffee文件中时,它工作得很好。

But , when I try to modularize things by moving the map code out into a separate OpenLayerMap Coffeescript class, no errors raise, but it just doesn't work. 但是 ,当我尝试通过将地图代码移到一个单独的OpenLayerMap Coffeescript类中来对事物进行模块化时,不会出现任何错误,但这是行不通的。 Here's what I've done. 这就是我所做的。 (I'm pretty sure I'm including things correctly. The class is available from my main file, as are its methods and attributes): (我很确定我正确地包含了这些东西。该类以及它的方法和属性都可以从我的主文件中获得):

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

I then call it in that previous file like so: 然后,我在先前的文件中将其命名为:

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

I don't think the OpenLayers details around projections, etc, are relevant. 我认为OpenLayers围绕投影等的细节并不重要。 What matters is that mapId is being passed in and used correctly, and if I throw a debugger in the paint() function, the debugger is hit, and all the attributes available at that point look good to me. 重要的是, mapId正在传入并正确使用,如果我将调试器扔到paint()函数中,则该调试器将被命中,并且那时所有可用的属性对我来说都是很好的。 The class is being included correctly, etc. But , no map is being painted. 正确包含了该类,等等。 但是 ,没有地图被绘制。

I have a Ruby background, and I think I'm confused by the effects and side-effects of the paint() function. 我有Ruby背景,我想我对paint()函数的效果和副作用感到困惑。 Why would it behave differently in a different file, if it's essentially identical behavior? 如果它本质上是相同的行为,为什么在不同的文件中表现不同?

Any ideas why this is failing (silently)? 有任何想法为什么会失败(无声)? It's driving me a little nuts. 它让我有点发疯。

I believe your use of @ inside your map property is causing the issue. 我相信您在地图属性中使用@会导致此问题。 Instead of accessing the current instance of OpenLayersMap you are calling the static property mapId on OpenLayersMap . 而不是访问的当前实例的OpenLayersMap您呼叫的静态属性mapIdOpenLayersMap For example: 例如:

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

Will compile into: 将编译为:

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

You will need to make map a method to access @mapId set in the constructor. 您将需要使map成为访问构造函数中设置的@mapId的方法。

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

I fully agree with Kyle Needham's explanation , but I want to propose another solution. 我完全同意Kyle Needham的解释 ,但我想提出另一种解决方案。

To fix your code simply move map assignment from class prototype to its constructor: 要修复代码,只需将map分配从类原型移至其构造函数:

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

You should consider moving fromProjection , toProjection , mapnik and markers definition to the constructor as well. 您还应该考虑从fromProjectiontoProjectionmapnikmarkers定义移至构造函数。

In your current implementation all instances of OpenLayersMap will have the same markers value, eg: 在您当前的实现中, OpenLayersMap所有实例将具有相同的markers值,例如:

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

So, by mutating l1.markers you'll not only affect all existing instances of OpenLayersMap class, but will change its prototype as well. 因此,通过l1.markers您不仅会影响OpenLayersMap类的所有现有实例,还将改变其原型。

It means that by mutating any of this four properties in any instance of OpenLayersMap class you'll make the same change to all other instances. 这意味着,通过在OpenLayersMap类的任何实例中更改这四个属性中的任何一个,您将对所有其他实例进行相同的更改。

If all this classes ( Projection , Layer and Markers ) are immutable (ie provide a bunch of helpers, but hold no state) then your implementation is the correct on, but I doubt that anyone would bother himself wrapping a bunch of stateless helpers into class. 如果所有这些类( ProjectionLayerMarkers )都是不可变的(即提供一堆帮助器,但是不保持任何状态),那么您的实现是正确的,但是我怀疑有人会费心将一堆无状态的帮助器包装到类中。

So, consider changing your code to: 因此,考虑将代码更改为:

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"

In this case each instance of OpenLayersMap will have its own fromProjection , toProjection , mapnik and markers . 在这种情况下,每个OpenLayersMap实例将具有其自己的fromProjectiontoProjectionmapnikmarkers

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

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