簡體   English   中英

Javascript變量范圍問題-錯誤:TypeError:this.graphics未定義

[英]Javascript Variable Scope Issue - Error: TypeError: this.graphics is undefined

我知道這個問題已經死了,但是我還是不明白。 我已經閱讀了StackOverFlow自己的“ this”關鍵字說明(以及其中的Mike West文章)以及其他與范圍相關的問題。 我不知道為什么我不明白,所以我向更精明的JavaScript開發人員尋求幫助。

從代碼和注釋中,它應該是相當自我解釋的。 但是它正在查詢ESRI地圖服務,返回圖形並將其放置在地圖上。

但是問題出在showResults函數中,我將其稱為this.graphics ,這是地圖的graphics屬性(圖形層)。 我知道它現在不在范圍內(花了更多時間弄清楚我想承認的時間),但是如何才能將其放回范圍內以便使用呢? 即使我已經對代碼進行了實質性的更改...

define([
"dojo/_base/declare",
"dojo/on",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"dijit/form/Button",
"dijit/form/Form",
"dijit/form/FilteringSelect",
"dijit/form/ValidationTextBox",
"dojo/_base/array",
"dojo/_base/Color",
"dojo/_base/lang",
"esri/tasks/find",
"dojo/text!./Find/templates/Find.html"
], function(declare, on, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, Button, Form, FilteringSelect, ValidationTextBox, array, Color, lang, find, FindTemplate) {

//anonymous function to load CSS files required for this module
(function() {
    var css = [require.toUrl("gis/dijit/Find/css/Find.css")];
    var head = document.getElementsByTagName("head").item(0),
        link;
    for(var i = 0, il = css.length; i < il; i++) {
        link = document.createElement("link");
        link.type = "text/css";
        link.rel = "stylesheet";
        link.href = css[i].toString();
        head.appendChild(link);
    }
}());

// Query Dijit
return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
    widgetsInTemplate: true,
    templateString: FindTemplate,
    graphics: null,
    findTask: null,
    findParams: null,
    results: [],
    serverError: null,
    queryLayer: null,
    searchText: null,
    postCreate: function() {
        // Method is used to call a superclass method. It's good practice to assume that you are overriding a method that may 
        // do something important in a class up the inheritance chain
        this.inherited(arguments);

        // Create graphics layer and add it to the map
        this.graphics = new esri.layers.GraphicsLayer({id:"queryGraphics"});
        this.map.addLayer(this.graphics);

        // Create find task with url to map service
        this.findTask = new esri.tasks.FindTask("arcgis/rest/services/MapServer");

        // Create find parameters and define known values
        this.findParams = new esri.tasks.FindParameters();     
        this.findParams.outSpatialReference = this.map.spatialReference;
        this.findParams.returnGeometry = true;
        this.findParams.layerIds = [1];
        this.findParams.searchFields = ["OBJECTID", "Gauge ID", "FV_ID", "FDC_ID", "Flood_Stage", "Flood_Line", "Municipality", "WATERSHED"]; 

        // Listen for Submit button click
        on(this.submitButton, 'click', lang.hitch(this, 'execute'));
    },
    // Submit button click event
    execute: function execute() {   
        // Set the WHERE search text
        this.findParams.searchText = dojo.byId("searchText").value;
        // Sends a request to the ArcGIS REST map service resource to perform a search based 
        // on the FindParameters specified in the findParameters argument. On completion, the 
        // onComplete event is fired and the optional callback function is invoked.
        this.findTask.execute(this.findParams, this.showResults, this.showError); 
    },
    // Fires when the find operation is complete and returns an array of FindResult
    showResults: function showResults(results) {
        this.graphics.clear();
        // Build an array of attribute information and add each found graphic to the map
        dojo.forEach(results, function(result) {
            var symbol;
            switch(result.feature.geometry.type) {
                case "point":
                    symbol = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_CIRCLE, 10, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new Color([255, 0, 0]), 1), new Color([255, 0, 0, 1.0]));
                    break;
                case "polyline":
                    symbol = new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_DASH, new Color([255, 0, 0]), 1);
                    break;
                case "polygon":
                    symbol = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_DASHDOT, new Color([255, 0, 0]), 2), new Color([255, 255, 0, 0.0]));
                    break;
                default:
                    symbol = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_CIRCLE, 10, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new Color([255, 0, 0]), 1), new Color([255, 0, 0, 1.0]));
            }
            var graphic = new esri.Graphic(result.feature.geometry, symbol);
            this.graphics.add(graphic);
        });
    },
    // Fires if the find execution fails to complete
    showError: function showError(serverError) {
        alert("The server encountered an error. Error: " + serverError);
    }
});
});

回答后更新:

因此,解決這個問題的不是一個答案,而是兩個答案的結合。 我結合了布法羅的答案

this.findTask.execute(this.findParams, lang.hitch(this, this.showResults), this.showError);

布法羅評論克雷格的回答

dojo.forEach(results, function(result) {  
...
}, this);

但克雷格(Craig's)也會在這里工作。 我敢肯定,這與泰米爾人的回答相結合也是可以的。

因此,我將Buffalo標記為答案,但所有這三者對於任何進一步的讀者都是值得關注的。

您可以使用Function.bind (請注意,並非所有瀏覽器都支持它)。

更改:

this.findTask.execute(this.findParams, this.showResults, this.showError); 

至:

this.findTask.execute(this.findParams, this.showResults.bind(this), this.showError); 

或(如果您擔心Function.bind瀏覽器支持):

使用closureFunction.apply

execute: function execute() {  
...
...
  var self = this;
  this.findTask.execute(this.findParams, function() {
    self.showResults.apply(self, arguments);
  }, this.showError); 
}

dojo/_base/langhitch方法將是您最好的朋友。 我假設findTask函數所做的是執行一些異步請求,然后使用結果調用第二個參數。

首先,將dojo/_base/lang添加到您的“依賴關系”列表中。

然后,換行

this.findTask.execute(this.findParams, this.showResults, this.showError); 

this.findTask.execute(this.findParams, lang.hitch(this,this.showResults), this.showError); 

lang#hitch所做的是獲取第一個參數(在本例中為小部件的實例),並使其成為執行第二個參數時的作用域。 在這種情況下,我們希望showResults在當前范圍內執行。

您的問題是以下代碼

    dojo.forEach(results, function(result) {

        ...

        this.graphics.add(graphic);
    });

執行的函數沒有小部件的范圍。 做了:

    dojo.forEach(results, lang.hitch(this, function(result) {

    }));

暫無
暫無

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

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