是否有可能在这里避免全球化?它值得吗?

时间:2015-02-20 00:14:35

标签: javascript google-maps kendo-ui

我有一个显示谷歌地图的网络应用程序。当用户单击地图上多边形的某个位置时,同一页面上的一个剑道网格将通过一个kendo数据源重复的ajax调用填充。

当kendo网格提取数据时,我也使用相同的数据填充谷歌地图上的工具提示。此工具提示需要显示在用户单击的相同位置。

为了传递此次点击的坐标,我正在使用全局变量。 我想知道是否可以避免它,以及是否值得这么麻烦。

以下是我的代码的摘录。

定义全局:

var clickLatLng;

在地图上订阅点击事件:

google.maps.event.addListener(polygon, 'click', function(event) {
    //Keep track of coordinates in a global
    clickLatLng = event.latLng;

    // initiate the ajax call to get the data
    dataSource.read(this.objInfo.id);

    // update grid view
    var grid = $("#grid").data("kendoGrid");
    grid.setDataSource(dataSource);
    grid.refresh();
});

定义数据源:

var dataSource = new kendo.data.DataSource({
    transport: {
        read: {
            url: "/getdata",
            type: "GET",
            dataType: "json",
            contentType: "application/json"
        }
    },
    schema: {
        data: function (response) {
            var events = [];

            var eventList = response.EventList;
            if (!eventList) {
                return events;
            }

            // This fills events from eventList
            populateEvents(events, eventList);

            // see below
            setToolTipValues(events);

            return events;
        },
        ...
    }
});

显示工具提示:

var setToolTipValues = function (events) {
    var infoWindow = new google.maps.InfoWindow();
    infoWindow.setContent(getTooltipConent(events));
    // here we use the global saved earlier to display the tooltip at the correct coordinates
    infoWindow.setPosition({ lat: clickLatLng.lat(), lng: clickLatLng.lng() });
    // map is also global I'm guessing there is no work around that
    infoWindow.open(map);
}

更新:要添加更多信息,上面的代码位于pageHelper.js中 pageHelper.js看起来像这样:

var pageHelper = function($, google, model) {

    var clickLatLng;
    ...    
}

这就是从页面调用的方式:

<script type="text/javascript">

    var model = ...;  //the ... bit comes from the server
    pageHelper($, google, model);
</script>

更新2 事件顺序:

  • 用户点击poligon
  • google.maps.event.addListener(polygon代码触发
  • 调用dataSource.read来启动ajax调用
  • 当ajax调用结束时data: function (response) {被触发
  • 调用setToolTipValues以显示工具提示

1 个答案:

答案 0 :(得分:2)

如果你想存储一个值供以后的其他事件消费,你有几个不是全局的选择:

  1. 您可以创建一个公共闭包(通常是IIFE),其中包含需要访问该值的所有代码,并将该值存储在闭包中的局部变量中。

  2. 您可以将值存储为某个现有对象的属性,以便需要使用该值的所有代码都可以访问。这可以是DOM对象或代码中的其他对象。 jQuery的.data()提供了一种简单的方法,可以在不使用全局的情况下将值与DOM对象相关联。

  3. 您可以创建单个全局命名空间对象,并将您的值作为属性放在该单个命名空间对象上。虽然这使用全局,但它允许您拥有许多全局属性,而在全局命名空间中只使用一个名称。

  4. 如果该值被用作一个主事件触发器的所有部分,那么您通常可以找到一种方法来传递变量,以便事件处理的其他部分可以使用原始值而不是将其存储在全球化的。我无法告诉代码中事件的确切顺序,以了解这是否可行。

  5. 通常,出于各种原因避免使用全局变量是个好主意。这不是一个严格的规则,但它是一个通常被认为是良好实践的指南。如果你发现需要多个全局变量,你也可以使用一个全局命名空间对象(这就像jQuery那样的框架),所以你只需创建一个新的全局可访问符号。


    根据OP的一些说明进行更新:

    听起来你根本就没有将它存储在全局中,而是它在一个闭包中的局部变量中。这可能只是你需要做的事情,因为将它存储在其他地方确实没有多大的优势。

    因为你想在系统的某些其他部分间接调用的方法中使用该值,所以你不能直接将值作为函数参数传递,因此典型的Javascript解决方案是将它存储在父关闭中,然后您可以在稍后调用它时从回调函数访问它。这是此类问题的常见Javascript设计模式。

    所以,如果这种理解是正确的:

    1. 用户点击了多边形。
    2. 您从数据源读取数据。
    3. 数据源中的schema.data方法由kendo框架调用,作为从该数据源读取的一部分。
    4. 您需要使用schema.data回调中的点击位置。
    5. 然后,您可以在这里做的最好的事情是将值放在父句子中,scheme.data回调可以到达原始点击位置。


      我可能会亲自对代码的结构方式进行一处更改。我可能会将该位置作为参数传递给setToolTipValues()并获取闭包变量以在schema.data()内传递给它。这使得setToolTipValues()与获取位置的方式无关,并且在一个无法避免的地方保持对该闭包变量的依赖。