单击视图时的应用器范围问题

Appcelerator scope issue when clicking a view

本文关键字:范围 问题 应用 视图 单击      更新时间:2023-09-26

我在这里疯了,试图弄清楚为什么我的变量的作用域不会从我的 Appcelerator 项目中的数据库中的 60 个项目的循环中获取正确的值。

我的地图标记显示正确的标签,但是当我单击它时,无论我尝试哪种范围组合,我都无法在警报中获得正确的值。它每次只返回第 60 个条目。

可能是小学生的错误,但这让我发疯了。

这是我的职能

function loadAnimals() {
var db = Ti.Database.open('myDB');
var getSpecies = db.execute('select * from species');
while (getSpecies.isValidRow()) {
    var speciesID = getSpecies.fieldByName('speciesnid');
    var speciesName = getSpecies.fieldByName('speciesname');
    var speciesDesc = getSpecies.fieldByName('speciesdescription');
    var speciesLatitude = getSpecies.fieldByName('specieslatitude');
    var speciesLongitude = getSpecies.fieldByName('specieslongitude');
    var speciesConStatus = getSpecies.fieldByName('speciesconservationstatus');
    var speciesMarkerFilename = getSpecies.fieldByName('speciesiconfilename'); 
    var speciesMarkerIcon = getSpecies.fieldByName('speciesmapicon');
    var speciesMarkerURI = getSpecies.fieldByName('speciesmapiconurl');
    var speciesImageFullPath = speciesMarkerURI.replace("public://", "http://myurl.com/");
    var speciesImageFullPath = speciesImageFullPath.replace(" ", "%20");
    var imageFile = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, speciesMarkerIcon);
    var iconFile = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, speciesMarkerFilename);

        var annotationView = Ti.UI.createView({
            backgroundColor: '#222222',
            width: 150,
            height: 75,
            layout:'vertical'
        });
        var addtoTourView = Ti.UI.createView({
            height:20,
            backgroundColor:'#6ea108'
        });

        var addtoTourTitle = Ti.UI.createLabel({
            color: '#FFF',
            text: 'ADD TO TOUR',
            width: 150,
            height: 15,
            top:3,
            textAlign: 'center',
            font: {
                fontSize: 14,
                fontWeight: 'bold'
            }
        });
        var annotationTitle = Ti.UI.createLabel({
            color: '#FFF',
            text: 'test',
            width: 150,
            height:15,
            top:0,
            textAlign: 'center',
            font: {
                fontSize: 14,
                fontWeight: 'normal'
            }
        });
        var blankView = Ti.UI.createView({
            backgroundColor: '#222222',
            width: 1,
            height: 73,
            borderRadius: 0
        });
        annotationView.add(addtoTourView);
        addtoTourView.add(addtoTourTitle);
        annotationView.add(annotationTitle);
        annotations.push(Map.createAnnotation({
            latitude: speciesLatitude,
            longitude: speciesLongitude,
            title: ' ',
            //pincolor: Map.ANNOTATION_RED,
            image: iconFile,
            animate: true,
            myid: speciesID,
            rightView: annotationView,
            leftView: blankView
        }));
        addtoTourView.addEventListener('click', function(e) {
            //alert(speciesName + ' has dded to Tour');
            var dialog = Ti.UI.createAlertDialog({
                message: 'Added to your Tour',
                ok: 'Continue',
                title: speciesName //this is the 60th entry, not the correct one
              });
              dialog.show();
            // do the insert into the DB
            var db = Ti.Database.open('myDB');
            db.execute('INSERT INTO tour (speciesnid) VALUES (?)', speciesID); // same with this ID, needs to the correct ID
            db.close();
        });
        annotationTitle.text = speciesName;

    //load up the next record
    getSpecies.next();
}; 
// close the database
getSpecies.close();
// add markers to map
mapview.annotations = annotations;

};//加载结束动物功能

谁能建议我做错了什么?

迈克尔斯的解决方案听起来是正确的。

无论如何,让我发布我要说的话。我专注于解释范围问题,为什么你的代码没有达到你的预期。


在javascript中,作用域绑定到函数。 当你在循环中声明一个变量(for/while/do...)时,事情可能会变得有点混乱。 您不是在创建新变量,您只是覆盖具有该名称的第一个(也是唯一的)变量的值。

因此,您在函数 loadAnimals 中有 1 个变量,称为物种名称。 在 while-循环中,您只需覆盖该变量的值。 在第 60 次迭代之后,变量只会记住您设置的最后一件事。

当客户端点击标记时,循环完成,该值很久以前就设置好了。


注意:您的地图服务可能提供了解决方案,但我不知道。

  • 1 个解决方案:"这个"。

"this"变量告诉您受影响的内容。 在 onClick 回调中,这是单击的元素。

您的问题的解决方案可能涉及"这个"。 但我不确定具体如何。

这是我的意思的一个例子。

<h2>Click on the animal</h2>
<p>dog</p>
<p>cat</p>
<p>hamster</p>
<script>
function loadAnimals() {
  var speciesName = '';
  var animalElements = document.getElementsByTagName('p');
  for (var i=0; i<animalElements.length; i++) {
    speciesName = animalElements[i].innerHTML ; // notice, this variable will be overridden, so this variable is useless within the onClick callback.
    animalElements[i].addEventListener('click', function(e) {
      // variable 'this' is the <p> that was clicked on.  
      var value_clicked_on = this.innerHTML;
      alert(value_clicked_on);
    });
  }
}
window.onload = loadAnimals;
</script>

创建要添加到地图的注释数组时,请将标题添加到注释参数以及使用键 - myid 设置的物种 ID。

annotations.push(Map.createAnnotation({
    latitude: speciesLatitude,
    longitude: speciesLongitude,
    title: ' ',
    //pincolor: Map.ANNOTATION_RED,
    image: iconFile,
    animate: true,  
    myid: speciesID,           // We'll be querying this
    myname: speciesName,       // and also this
    rightView: annotationView,
    leftView: blankView
}));

然后将事件侦听器添加到地图对象而不是每个单独的注释对象上。这样可以更有效地管理内存,并且是添加内存的正确方法。不要为每个注释添加事件侦听器,这是不好的做法。

// Handle click events on any annotations on this map.
mapview.addEventListener('click', function(evt) {
    Ti.API.info("speciesID " + evt.annotation.myid + " clicked, speciesName: " + evt.annotation.myname);
});

在这个单一的事件侦听器上,您现在可以通过检查每个注释的各个属性来创建警报对话框和数据库插入

evt.annotation

在 Map 对象上,您还可以执行以下操作:

click事件包括一个值,您可以查询该值clicksource

此点击源将让您知道源 - 您可以在事件侦听器中使用的源 - pin, annotation, leftButton, rightButton, leftView, rightView, title, or subtitle

触发事件的源对象也可用 - source 。然后,您可以测试点击源是否不为 null,并且源是否来自要放置触发器的"添加到游览"元素。仍然从evt.annotation获取所有注释属性