2

私はここで立ち往生しています、どんなヒントでもいいでしょう。
Objects オブジェクト [] の配列と divnames [] の配列があります。私のオブジェクトには、play() や stop() などの関数があります。オブジェクトとその機能は複数の状況でテストされ、機能しています。今、私はdivnames []を繰り返し、適切なオブジェクト[]のアクションをマウスオーバー、マウスアウト、クリックに割り当てようとしています。
StackOverflow の別のスレッドで見つけた解決策で修正した閉鎖の問題がありました。それはうまくいきます。しかし、残っている問題は、後でロードされる div にマウスオーバーなどのアクションが割り当てられないことです。彼らは最初からページにあるオブジェクトに取り組んでいます。
ここに私が持っているものがあります:

$(function(){
    for (var i=0, len=divnames.length; i<len; i++) {
        if(divnames[i]){
            (function( ) { // anonymous function to fix closures
                var index = i; // also needed to fix closures
                $('#'+divnames[index]).on("click", function() {
                    objects[index].play();
                    loadContent(divnames[index]+".php");
                });
            })( ); // direct function execution to fix closures
        }
    }
});

上記のように、クロージャーの問題は 2 つのコメント行によって修正されます。それらを除外すると、for ループの最後の実行のみが適用されます。今のように、それはうまくいきます。
しかし、機能しないのは、セレクターに一致するdivにもクリック機能を適用する必要があるが、まだロードされていないことです。
しかし、同じ機能を持つコードが for ループ内でクロージャー修正なしで反復されない場合、それは機能します。これは、正しく理解すれば .on() の動作が予想されるためです。

では、両方の必要な機能を機能させるにはどうすればよいですか?

お時間をいただきありがとうございます。

- - 編集 - -

要求された追加情報:

var divnames = [];
divnames[0] = "home";
divnames[1] = "about";
divnames[2] = "projects";

function SpriteAnim (options) {
var timerId = 0; 
    var i = 0;
    this.status = 0;
this.init = function () {
    var element = document.getElementById(options.elementId);
    element.style.width = options.width + "px";
    element.style.height = options.height + "px";
    element.style.backgroundRepeat = "no-repeat";
    element.style.backgroundImage = "url(" + options.sprite + ")";
};
this.showFrame = function (which) {
    if (which < options.frames) {
                    i = which;
        element = document.getElementById(options.elementId);
        element.style.backgroundPosition = "0px -" + which * options.height + "px";
    }
};
this.play = function () {
            this.status = 2;
    timerId = setInterval(function () {
        if (i < (options.frames - 1)) {
                            i++;
            element = document.getElementById(options.elementId);
            element.style.backgroundPosition = "0px -" + i * options.height + "px";
                    } else {
                        clearInterval(timerId);
                        this.status = 1;
                    }
    }, 100);
};
}

すでにお察しのとおり、objects[] 配列には、objects[0]、objects[1]、objects[2] に 3 つの SpriteAnim オブジェクトが含まれています。

objects[0] = new SpriteAnim({
    width: 7,
    height: 7,
    frames: 8,
    sprite: "myanim1.png",
    elementId: "anim0"
});
objects[1] = new SpriteAnim({
    width: 7,
    height: 7,
    frames: 8,
    sprite: "myanim1.png",
    elementId: "anim1"
});
objects[2] = new SpriteAnim({
    width: 7,
    height: 7,
    frames: 8,
    sprite: "myanim2.png",
    elementId: "anim2"
});
4

2 に答える 2

4

イベント委任を使用し、要素自体ではなく親要素でこれらのイベントをリッスンする必要があります。このように、後で新しい要素を追加する場合、それらに再バインドする必要はありません。

$("#buttons").on("click", ".button", function(){
    console.log("You clicked on a .button element.");
});

この場合、 のクリック イベントにバインドします#buttonsが、呼び出し元の要素が selector に一致する場合のみ.buttonです。あなたのマークアップは、次のようなものになります。

<div id="buttons">
    <a class="button">Foo</a>
    <a class="button">Bar</a>
</div>

要素のいずれかでクリックが発生し.button、親にバブルアップすると#buttons、それが傍受され、ハンドラーが起動されます。

于 2012-10-28T03:01:01.220 に答える
1

これは、index がバインディング ステートメントの外で宣言されているためです。クリックがその呼び出しに入ると、オブジェクト[インデックス]が何であるかわかりません。

同じ構造を維持したい場合は、関数を次のように作り直してください。

$(function(){
    for (var i=0, len=divnames.length; i<len; i++) {
        if(divnames[i]){
            (function( ) { // anonymous function to fix closures
                var index = i; // also needed to fix closures
                $('#'+divnames[index]).on("click", function(e) {
                    switch ($(e.id).attr('name')){
                        case 'home':
                            objects[0].play();
                            loadContent('home.php');
                            break;
                        case 'about':
                        // do same
                        case 'projects':
                        // do same
                        default:
                            break;
                    }
                });
            })( ); // direct function execution to fix closures
        }
    }
});

現実的には、次のようにする必要があります。

$(document).on('click','div[name=home],div[name=projects],div[name=about]', function(){
    var name = $(this).attr('name');
    switch (name){
        case 'home':
            objects[0].play();
            break;
            // and so on
    }
    loadContent(name + '.php');
});

編集:

div をクリックすると、これだけが認識されます。

objects[index].play();
loadContent(divnames[index]+".php");
于 2012-10-28T04:26:55.200 に答える