14

JS セットアップにマスター オブジェクトがあります。

var myGarage = {
    cars: [
        {
            make: "Ford",
            model: "Escape",
            color: "Green",
            inuse: false
        },
        {
            make: "Dodge",
            model: "Viper"
            color: "Red",
            inuse: true
        },
        {
            make: "Toyota",
            model: "Camry"
            color: "Blue",
            inuse: false
        }
    ]
}

今、私は自分の車をループしてテーブルに置きます。テーブルには、車を「使用中」と「未使用」に切り替えるボタンもあります。

すべての行の DOM 要素を対応する車に関連付けるにはどうすればよいですか?「inuse」フラグを切り替えると、マスター オブジェクトを更新できますか?

4

4 に答える 4

18

オブジェクトをノードに直接アタッチできます。

var n = document.getElementById('green-ford-escape');
n.carObject = myGarage.cars[0];
n.onclick = function() {
  doSomethingWith(this.carObject);
}

あいまいさを取り除くのと同じように、場合によっては、参照する上記のイベント ハンドラーを次nの代わりに記述した方が明確thisです。

n.onclick = function() {
  doSomethingWith(n.carObject);
}

添付イベントからオブジェクトを直接参照することもできます。

var n = document.getElementById('green-ford-escape');
n.onclick = function() {
    doSomethingWith(myGarage.cars[0]);
}

後者の場合、グローバルである必要myGarageはありません。これを行うと、正しく動作することが期待できます。

(function(){

    var myGarage = { /* ... etc ... */ };

    var n = document.getElementById('green-ford-escape');
    n.onclick = function() {
        doSomethingWith(myGarage.cars[0]);
    }

})();

ノードのイベント関数はローカル変数を正しく「保持」し、効果的にプライベート変数を作成します。

Chrome/FF/IE コンソールでこれをテストできます。

var o = {a: 1};
var n = document.createElement('div');
n.innerHTML = "click me";
n.data = o;
n.onclick = function() { n.data.a++; console.log(n.data, o); }
document.body.appendChild(n);

クリックするたびに、a値が増加する 2 つの同一のオブジェクトがコンソールに記録されるはずです。

n.dataプリミティブに設定しても参照が作成されないことに注意してください。値をコピーします。

于 2013-04-19T20:44:47.130 に答える
9

と、オブジェクトをインターフェイスaddEventListenerに適合させるコンストラクターを検討することをお勧めします。eventListener

そうすれば、オブジェクト、要素、およびそのハンドラーを適切に関連付けることができます。

これを行うには、データに固有のコンストラクターを作成します。

function Car(props) {
    this.make = props.make;
    this.model = props.model;
   // and so on...

    this.element = document.createElement("div"); // or whatever

    document.body.appendChild(this.element);      // or whatever

    this.element.addEventListener("click", this, false);
}

次に、インターフェースを実装します。

Car.prototype.handleEvent = function(e) {
    switch (e.type) {
        case "click": this.click(e);
        // add other event types if needed
    }
}

.click()次に、プロトタイプにハンドラーを実装します。

Car.prototype.click = function(e) {
    // do something with this.element...
    this.element.style.color = "#F00";

    // ...and the other properties
    this.inuse = !this.inuse
}

したがって、配列をループして、Car各アイテムの新しいオブジェクトを作成するだけで、新しい要素が作成され、リスナーが追加されます。

myGarage.cars.forEach(function(obj) {
    new Car(obj)
})
于 2013-04-19T20:49:05.947 に答える
1

HTML5 data-* 属性を使用して、それがどの行であるかを調べることができます。あなたはこのようなことをしているに違いない

var table = $('<table>'); // Let's create a new table even if we have an empty table in our DOM. Simple reason: we will achieve single DOM operation (Faster)

for (var i=0; i<myGarbage.cars.length; i++) {
    // Create a new row and append to table
    var tr = $('<tr>').appendTo(table);

    var carObject = myGarbage.cars[i];
    // Traverse the JSON object for each car
    for (var key in carObject) {
        // Create other cells. I am doing the last one
        var td = $('<td>').appendTo(tr);
        var button = $('<button>').attr('data-carId', i).addClass('toggle-inuse').appendTo(td);
    }
}
// If en ampty table awaits me in DOM
$('#tableId').html(table.html());

次に、ボタンにイベントリスナーを追加します:-

$('.toggle-inuse').click(function() {
    var i = $(this).data('carId');
    myGarbage.cars[i].inuse = !myGarbage.cars[i].inuse; //Wow done
}

これを試してみてください!!

于 2013-04-19T21:03:23.393 に答える