用户控件范围内的全局JS变量?

时间:2021-07-21 20:31:41

Say you have a user control that uses a 3rd party JS API (uses dojo). You have a JS function loadMap that initialize some global variables for your control and hook up some events (from the 3rd party API) to your JS event handlers. In your event handlers you need to use the global variables you defined in loadMap.

假设您有一个使用第三方JS API的用户控件(使用dojo)。你有一个JS函数loadMap,它为你的控件初始化一些全局变量,并将一些事件(从第三方API)连接到你的JS事件处理程序。在事件处理程序中,您需要使用在loadMap中定义的全局变量。

Problem: If I have more than one instance of this control in the same page, the globals would overwrite each other and wouldnt work.

问题:如果我在同一页面中有多个此控件的实例,则全局变量将相互覆盖并且无法工作。

Question:
How can I write the JS to have global variables within the scope of a control instance, if that makes sense? or any suggestion that would solve my issue.

问题:如果有意义的话,如何编写JS以将全局变量置于控件实例的范围内?或任何可以解决我的问题的建议。

Here is my control JS code (I minimized it to just show the problem), my globals are defined in the first 3 lines

这是我的控制JS代码(我最小化它只显示问题),我的全局变量在前3行中定义

//create the global variables
var mapVar;
var geocoderVar;
var toolbarVar;

function loadMap(divMap, divSearch) {
    ...
    // create the map 
    mapVar = new esri.Map(divMap, {
        zoom: 0,
        minZoom: 0,
        maxZoom: 10,
        lods: lods
    });     

    // create the geocoder 
    if (geocoderVar === null) {
        geocoderVar = new esri.dijit.Geocoder({
            map: mapVar
        }, divSearch);
        geocoderVar.startup();
    }
     //Hook up event handlers
    dojo.connect(mapVar, "onExtentChange", checkScale);
    dojo.connect(mapVar, "onLoad", createToolbar);       
}

function createToolbar(themap) {
    dojo.connect(mapVar, "onClick", function (evt) {
        if (canDrop === true) {
                point = evt.mapPoint;
            mapVar.graphics.clear();
           ...
        }
        ...

    });
     //create the toolbar variable
    toolbarVar = new esri.toolbars.Draw(mapVar);
    ...
    dojo.connect(toolbarVar, "onDrawEnd", addToMap);
}

 function checkScale(extent, delta, outLevelChange, outLod) {

     if (outLod.level == 10) {
         canDrop = true;
         window[controlName + '_toolbarVar'].activate(esri.toolbars.Draw.POINT, { showTooltips: false });
     }
     else {
         window[controlName + '_toolbarVar'].deactivate();
         canDrop = false;
     }
 }
 ...

1 个解决方案

#1


1  

Give your code an anonymous local scope instead of writing everything globally:

为代码提供匿名的本地范围,而不是全局编写所有内容:

(function(any, globals, you, need, to, pass, in, as, an, instance){
  //All code local to your control goes here
  global = "etc..."

....
}(any, globals, you, need, to, pass, in, as, an, instance));

By passing globals in as themselves, their local version overrides the global and prevents interaction.

通过将globals作为自身传递,它们的本地版本会覆盖全局并阻止交互。

Edit: To do this from an external JS file, simply declare your code as a single function, and call it once for each time your control loads. You would then include the JS file only once on your template:

编辑:要从外部JS文件执行此操作,只需将代码声明为单个函数,并在每次控件加载时调用一次。然后,您只需在模板中包含一次JS文件:

in the js file:

在js文件中:

var myFuncLib = function(any, globals, you, need, to, pass, in, as, an, instance){
      //All code local to your control goes here
      global = "etc..."

    ....
    };

in your control:

在你的控制中:

<script>
myFuncLib(any, globals, you, need, to, pass, in, as, an, instance);
</script>

The globals passed in may be clsses/id's specific to the control, DOM elements, other library resources, etc.

传入的全局变量可能是clsses / id特定于控件,DOM元素,其他库资源等。

This solution is also approaching a library pattern called the "module pattern" There are a number of good resources available on this topic, not the least of which is the CommonJS spec (http://wiki.commonjs.org/wiki/Modules/1.1) for implementing it in libraries, and the many script loaders that use this pattern.

这个解决方案也接近一个名为“模块模式”的库模式。在这个主题上有许多可用的资源,其中最重要的是CommonJS规范(http://wiki.commonjs.org/wiki/Modules/ 1.1)在库中实现它,以及使用这种模式的许多脚本加载器。

#1


1  

Give your code an anonymous local scope instead of writing everything globally:

为代码提供匿名的本地范围,而不是全局编写所有内容:

(function(any, globals, you, need, to, pass, in, as, an, instance){
  //All code local to your control goes here
  global = "etc..."

....
}(any, globals, you, need, to, pass, in, as, an, instance));

By passing globals in as themselves, their local version overrides the global and prevents interaction.

通过将globals作为自身传递,它们的本地版本会覆盖全局并阻止交互。

Edit: To do this from an external JS file, simply declare your code as a single function, and call it once for each time your control loads. You would then include the JS file only once on your template:

编辑:要从外部JS文件执行此操作,只需将代码声明为单个函数,并在每次控件加载时调用一次。然后,您只需在模板中包含一次JS文件:

in the js file:

在js文件中:

var myFuncLib = function(any, globals, you, need, to, pass, in, as, an, instance){
      //All code local to your control goes here
      global = "etc..."

    ....
    };

in your control:

在你的控制中:

<script>
myFuncLib(any, globals, you, need, to, pass, in, as, an, instance);
</script>

The globals passed in may be clsses/id's specific to the control, DOM elements, other library resources, etc.

传入的全局变量可能是clsses / id特定于控件,DOM元素,其他库资源等。

This solution is also approaching a library pattern called the "module pattern" There are a number of good resources available on this topic, not the least of which is the CommonJS spec (http://wiki.commonjs.org/wiki/Modules/1.1) for implementing it in libraries, and the many script loaders that use this pattern.

这个解决方案也接近一个名为“模块模式”的库模式。在这个主题上有许多可用的资源,其中最重要的是CommonJS规范(http://wiki.commonjs.org/wiki/Modules/ 1.1)在库中实现它,以及使用这种模式的许多脚本加载器。