【问题标题】:Dojo AMD module changes reference of "this"Dojo AMD 模块更改了“this”的引用
【发布时间】:2013-10-03 22:51:05
【问题描述】:

对于我在尝试学习 AMD 风格的 Dojo 时看到的一些行为,我真的很困惑。当我实例化我的模块/对象时,“this”指的是我的构造函数中的对象。我调用了一个内部函数,该内部函数中的“this”指的是 Window 对象。因此,当我到达 this.attachMapEventHandlers 时,我得到一个“对象 [对象全局] 没有方法 'attachMapEventHandlers'”错误。我究竟做错了什么?更新:我找到了 lang.hitch,这似乎表明异步性质是让我绊倒的原因,但我对如何实施解决方案感到困惑。

我在 index.html 中的脚本:

require(["javascript/layout", "dijit/layout/ContentPane", "dijit/layout/BorderContainer", "dijit/layout/AccordionContainer", 
        "dojo/dom", "dojo/dom-attr", "dijit/Toolbar", "dijit/form/Button", "dijit/Dialog","dijit/ProgressBar", "dojo/domReady!"],
        function (layout, dom, domAttr) {
            mapControl = new layout();

layout.js:

define(["dojo/_base/declare"], function(declare) {
return declare(null, {
    action:"pan",
    activeMeasureTool:"",
    aerialLayer:"",
    legendLayers:"",
    loadedServices:"",
    popup:"",
    resizeId:0,
    constructor: function() {
        this.init();
    },
    init: function() {
        require(["esri/map", "esri/config", "esri/SpatialReference", "esri/geometry/Extent"], 
            function(Map, config, SpatialReference, Extent) {
            //custom map requires a proxy to function properly.
            esri.config.defaults.io.proxyUrl = "../sdc_devdata/proxy.php";

            var spatRef = new SpatialReference(2276);

            var startExtent = new Extent(2481416.32087491, 6963246.42495962, 2501196.36936991, 6980267.92469462, spatRef);
            var appFullExtent = new Extent(2396699.46935379, 6872369.60195443, 2607745.94404633, 7107335.22319087, spatRef);

            map = new Map("map", {extent: startExtent, isZoomSlider:true, logo:false, sliderStyle:"large"});
            this.attachMapEventHandlers();
            this.createLayers();
            this.handleLayerVisibilityChange();
        });
    },

【问题讨论】:

    标签: dojo amd


    【解决方案1】:

    您可以采取一些措施来解决此问题。

    首先,您可以将所需的依赖项添加到 define 数组中,这样您就无需在类的构造函数中执行异步请求。

    看起来像:

    define(["dojo/_base/declare", "esri/map", "esri/config", "esri/SpatialReference", "esri/geometry/Extent"], function (declare, Map, config, SpatialReference, Extent) {
      return declare(null, {
        action: "pan",
        activeMeasureTool: "",
        aerialLayer: "",
        legendLayers: "",
        loadedServices: "",
        popup: "",
        resizeId: 0,
        constructor: function () {
          this.init();
        },
        init: function () {
          //custom map requires a proxy to function properly.
          esri.config.defaults.io.proxyUrl = "../sdc_devdata/proxy.php";
    
          var spatRef = new SpatialReference(2276);
    
          var startExtent = new Extent(2481416.32087491, 6963246.42495962, 2501196.36936991, 6980267.92469462, spatRef);
          var appFullExtent = new Extent(2396699.46935379, 6872369.60195443, 2607745.94404633, 7107335.22319087, spatRef);
    
          map = new Map("map", {
            extent: startExtent,
            isZoomSlider: true,
            logo: false,
            sliderStyle: "large"
          });
          this.attachMapEventHandlers();
          this.createLayers();
          this.handleLayerVisibilityChange();
        }
      });
    });
    

    或者您可以在执行 require 时将 this 的当前范围保存到闭包中的某个内容

    init: function () {
      var that = this;
      require(["esri/map", "esri/config", "esri/SpatialReference", "esri/geometry/Extent"],
        function (Map, config, SpatialReference, Extent) {
          //custom map requires a proxy to function properly.
          esri.config.defaults.io.proxyUrl = "../sdc_devdata/proxy.php";
    
          var spatRef = new SpatialReference(2276);
    
          var startExtent = new Extent(2481416.32087491, 6963246.42495962, 2501196.36936991, 6980267.92469462, spatRef);
          var appFullExtent = new Extent(2396699.46935379, 6872369.60195443, 2607745.94404633, 7107335.22319087, spatRef);
    
          map = new Map("map", {
            extent: startExtent,
            isZoomSlider: true,
            logo: false,
            sliderStyle: "large"
          });
          that.attachMapEventHandlers();
          that.createLayers();
          that.handleLayerVisibilityChange();
        });
    },
    

    编辑:您的第三个选项是使用 lang.hitch,它允许您在回调函数中指定 this 的范围。要使用它,您需要将 dojo/_base/lang 添加到您的 define() 依赖列表中,并将 require 回调包装在 lang.hitch(this, function(){});

    define(["dojo/_base/declare", "dojo/_base/lang"], function (declare, lang) {
      return declare(null, {
        //...
        init: function () {
          require(["esri/map", "esri/config", "esri/SpatialReference", "esri/geometry/Extent"],
            lang.hitch(this, function (Map, config, SpatialReference, Extent) {
              //this now refers to the instance of the class
            }));
        }
    
      });
    });
    

    我强烈建议使用第一个选项,因为它与 AMD 的整个使用一致(在执行之前声明模块需要哪些依赖项,而不是动态加载它)。

    【讨论】:

    • 感谢您的回答。接受第一个
    【解决方案2】:

    你可以把'this'放在另一个变量中,比如_this,并在你的内部函数中使用_this,比如

    init: function() {
             var _this= this;
            require(["esri/map", "esri/config", "esri/SpatialReference", "esri/geometry/Extent"], 
                function(Map, config, SpatialReference, Extent) {
                ...
                _this.attachMapEventHandlers();
                _this.createLayers();
                _this.handleLayerVisibilityChange(); 
    

    【讨论】:

      猜你喜欢
      • 2014-10-08
      • 1970-01-01
      • 2013-06-10
      • 2013-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-10
      相关资源
      最近更新 更多