Appcelerator + Alloy + Eval to Loop through Objects - $ 打破它

Appcelerator + Alloy + Eval to Loop through Objects - $ breaks it

我在屏幕上有 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 打破了它。想法?谢谢。

除了那个错误,还有很多事情需要你注意。

第一件事是彻底改造你的 UI 结构。当前不建议手动设置 left/bottom/top/right 属性,因为您确实可以使用布局类型正确创建视图。

从您的 XML 代码来看,您似乎正在创建一个 16 列 x 25 行 的网格视图,每个视图都有一个 1.5% 的左填充和 2.3% 的顶部填充(这里你把它作为底部)你目前设计它的主要问题是手动使用 left/bottom 属性 AND 当然 为什么有人会手动创建 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 个位置进行更改。