【问题标题】:Appcelerator + Alloy + Eval to Loop through Objects - $ breaks itAppcelerator + Alloy + Eval 循环遍历对象 - $ 打破它
【发布时间】:2017-10-25 16:56:03
【问题描述】:

我在屏幕上有 384 个对象,我需要按特定顺序遍历它们,根据不断变化的变量更改它们的属性。以下是 .xml 文件中对象的样子:

    <View formFactor="tablet" id="res1_1" class="resBit" left="1.5%" bottom="25.0%" />
    <View formFactor="tablet" id="res1_2" class="resBit" left="1.5%" bottom="27.3%" />
    <View formFactor="tablet" id="res1_3" class="resBit" left="1.5%" bottom="29.6%" />
    <View formFactor="tablet" id="res1_4" class="resBit" left="1.5%" bottom="31.9%" />
    [...]
    <View formFactor="tablet" id="res16_22" class="resBit" left="93.0%" bottom="73.3%" />
    <View formFactor="tablet" id="res16_23" class="resBit" left="93.0%" bottom="75.6%" />
    <View formFactor="tablet" id="res16_24" class="resBit" left="93.0%" bottom="77.9%" />

这是 javascript 的样子:

// theValues rotates between a set of 100 or so such combinations
theValues = "2,2,3,4,5,5,4,3,2,2,3,4,5,5,4,3".split(",");

// Start on the left and move right
for (i=1; i<17; i++) {
    // Start at the bottom and move up
    for (ii=1; ii<25; ii++) {
        if (ii < (theValues[i-1]) - 1) {
            // Make first row solid
            if (i == 1) { eval('$.res' + i + '_' + ii + '.setOpacity(1);'); }
            // Paint reds
            eval('$.res' + i + '_' + ii + '.setBackgroundColor("red");');
        }
    }
}

我得到的错误是:

[ERROR] :  TiExceptionHandler: (main) [10567,152803] ----- Titanium Javascript Runtime Error -----
[ERROR] :  TiExceptionHandler: (main) [0,152803] - In undefined:1,1
[ERROR] :  TiExceptionHandler: (main) [0,152803] - Message: Uncaught ReferenceError: $ is not defined
[ERROR] :  TiExceptionHandler: (main) [1,152804] - Source: $.res1_1.setOpacity(1);

如果我直接在代码中写$.res1_1.setOpacity(1);,它就可以工作。破坏它的是 eval 。想法?谢谢。

【问题讨论】:

  • 有一段时间没有使用 appcelerator 但我认为你可以这样做 if (i == 1) { $['res' + i + '_' + ii].setOpacity(1); }
  • 成功了!请将其添加为答案,以便我接受。 :)
  • 只是为评论点赞,没关系 :) 很高兴它奏效了。

标签: javascript loops runtime-error appcelerator titanium-alloy


【解决方案1】:

除了该错误之外,您还需要注意很多事情。

首先要彻底检查您的 UI 结构。目前不建议手动设置 left/bottom/top/right 属性,当您真正可以使用布局类型正确创建视图时。

从您的 XML 代码的外观来看,您似乎正在创建一个 16 列 x 25 行的网格视图,每个视图的 左填充为 1.5%,顶部填充为2.3%(这里你把它作为底部)你目前设计它的主要问题是手动使用左/底部属性当然为什么有人会手动创建 384 个视图 :) .. 这样做需要很大的耐心 & 至少我没有 :)

现在推荐的创建这样的 UI 的方法是这样的:

template.xml

<Alloy>
    <View class="resBit" left="1.5%" top="2.3%" />
</Alloy>

your_view.xml

<View id='parentContainer' formFactor="tablet" layout='horizontal' horizontalWrap='true' right='1.5%'>
    ..... here comes your those resBit views created dynamically
    // formFactor property is only set to parent container which also applies to its child container, so no need to set it on all 384 child views as you did

    // horizontalWrap property ensures that child-views which are going out of bound, will be created in
    // next row & thus it creates a grid-view automatically while using proper sizes so the last or
    // 16th view fits to the end of parent view.
</View>

your_view.js

// create child-views dynamically like this
for (var i=1; i<=384; i++) {
    // you can pass any required arguments here needed to create child-views
    var templateView = Alloy.createController('template', {
        position : i
    }).getView();

    $.parentContainer.add(templateView);
}

template.js

var pos = $.args.position;

// if it's the last or 16th child-view in each row, then set its width to fill the parent width, which will make sure that your next child-view will move to a new row.
// it's necessary because sometimes while using %age dimensions, there might be a few pixels calculation error which can create the 16th child-view to next row

if ((pos % 16) == 0) {
    $.template.width = Ti.UI.FILL;
}

最后,由于您没有 res12_14 等 ID,您仍然可以像这样访问所有子视图:

your_view.js

// theValues rotates between a set of 100 or so such combinations
theValues = "2,2,3,4,5,5,4,3,2,2,3,4,5,5,4,3".split(",");

// gives you all child-views in an array
var child_views = $.parentContainer.children;

// Start on the left and move right
for (i=1; i<17; i++) {

    // Start at the bottom and move up
    for (ii=1; ii<25; ii++) {
        if (ii < (theValues[i-1]) - 1) {
            var currentChildPos = i * ii - 1;       // since we started loop from 1 & array index starts from 0
            // Make first row solid
            if (i == 1) {
                child_views[currentChildPos].setOpacity(1);
            }

            // Paint reds
            child_views[currentChildPos].setBackgroundColor("red");
        }
    }
}

这才是你真正应该使用 Alloy MVC 框架的方式,编写更少的代码,编写更多可维护的代码。如果您需要对这些 resBit 视图进行任何更改,那么您现在可以在 template.xml 文件中进行更改,而不是之前代码中的 384 位。

【讨论】:

  • 有趣的情况。感谢您的洞察力。 ?
猜你喜欢
  • 1970-01-01
  • 2020-06-09
  • 1970-01-01
  • 2020-04-30
  • 2017-06-12
  • 2015-10-31
  • 2014-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多