2013-04-19 9 views
11

ich ein Master-Objekt in meinem JS-Setup habe, d.h .:wie ein Objekt mit einem DOM-Elemente verknüpfen

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 
     } 
    ] 
} 

Jetzt habe ich eine Schleife über meine Autos und in einem Tisch. In der Tabelle habe ich auch einen Knopf, mit dem ich das Auto als "in Gebrauch" und "nicht in Gebrauch" schalten kann.

Wie kann ich das DOM-Element jeder Zeile mit dem entsprechenden Auto verknüpfen, so dass ich das Master-Objekt aktualisieren kann, wenn ich das Flag "inuse" umschalte?

+0

Haben Sie die '.data()' Methode von jQuery berücksichtigt? – Barmar

+0

habe ich, aber wie speichere ich einen Verweis auf jedes Auto-Objekt im Inneren? – Steve

+0

Etwas wie '$ (" ") .data (Auto) .appendTo (Tabelle)' – Barmar

Antwort

7

Ich würde vorschlagen, addEventListener und einen Konstruktor, der Ihre Objekte an die eventListener Schnittstelle entspricht.

Auf diese Weise können Sie eine schöne Verbindung zwischen Ihrem Objekt, Ihrem Element und seinen Handlern haben.

Erstellen Sie dazu einen Konstruktor, der für Ihre Daten spezifisch ist.

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); 
} 

implementieren Sie dann die Schnittstelle:

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

Dann implementieren Ihre .click() Handler auf dem Prototyp.

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

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

Also dann können Sie nur eine Schleife über den Array, und ein neues Car Objekt für jedes Element, und es wird das neue Element erstellen und den Hörer (n) hinzufügen.

myGarage.cars.forEach(function(obj) { 
    new Car(obj) 
}) 
+0

er sagte, dass er jQuery verwendet, so dass jeder von diesen zu Einzeilern abgekürzt werden kann. – Barmar

+0

Vielen Dank für die detaillierte Erklärung. Ich mache es tatsächlich sehr ähnlich. Die obige Beschreibung war nur eine kurze Erklärung, um mein tatsächliches Problem zu lösen: Wie speichere ich einen Verweis auf jedes Autoobjekt (innerhalb des myGarage-Objekts) innerhalb des 'tr' rowElement, so dass ich das ursprüngliche Objekt innerhalb eines Klicks leicht aktualisieren kann Handler. – Steve

+0

@Barmar: Vielleicht vermisse ich es, aber ich sehe nicht, wo es heißt "mit jQuery". Ich sehe das Tag, aber das ist es. –

0

Sie möchten eine Art ID oder eine bestimmte Zeile in Ihren Informationen haben, sonst müssen Sie sich auf den Array-Index verlassen. In jedem Fall möchten Sie die Daten mit data attributes speichern.

Also, wenn Sie eine Schleife durch:

for (var i = 0, l = array.length; i < l; i++) { 
    var div = '<tr data-car="' + JSON.stringify(array[i]) + '" data-index="' + i + '"><td></td></tr>' 
} 

Und auf dem Click-Ereignisse:

$('button').click(function() { 
    var carIndex = $(this).closest('tr').attr('data-index'); 
    var carData = $(this).closest('tr').attr('data-car'); 
    if (carData) carData = JSON.parse(carData); 

    myGarage.cars[carIndex].inUse = true; 
}) 

Wenn Sie die Daten an den DOM binden, können Sie nicht einmal die tatsächlichen JS Daten aktualisieren . Sie können jede Zeile in der Tabelle durchlaufen und das Datenobjekt, aus dem Sie die Tabelle erstellt haben, neu erstellen.

+0

Das Problem mit diesem Ansatz ist, dass ich eine Kopie von jedem Auto-Objekt in der "Data-Attribut" speichern. Das ist nicht was ich will. Ich möchte einen Verweis auf das ursprüngliche Objekt im Master-Objekt. – Steve

+0

Also nur den Index mit Datenattributen speichern? Es gibt keine sichere Möglichkeit, einen Verweis auf ein DOM-Element zu erhalten. Wenn Sie es mit jQuery finden und es in Ihrem Auto-Objekt speichern, wird die jQuery-Referenz nicht zuverlässig festgelegt bleiben. Möglicherweise können Sie das rohe Tabellenelement (document.getElementById zum Beispiel) in Ihrem myGarage-Hauptobjekt speichern, jedoch müssen Sie die Referenzaufenthalte zwischen Funktionsaufrufen testen. –

+0

Warum wir carIndex in Zeile einfügen ... Warum fügen Sie es nicht auf der Schaltfläche selbst hinzu? Es wird mir eine DOM-Abfrage speichern, um die nächste Zeile zu finden. Meine Antwort tut das Gleiche. Lass es mich wissen, wenn es einen Grund dafür gibt. – sachinjain024

14

Sie können tatsächlich ein Objekt direkt mit einem Knoten befestigen:

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

Für die gleiche Mehrdeutigkeit zu entfernen, in einigen Fällen, es ist mehr klar die obigen Ereignishandler schreiben, um n statt this zu verweisen:

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

Sie können auch direkt auf das Objekt aus dem beigefügten Ereignisse beziehen:

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

In letzterem Fall muss myGaragenicht global sein. Sie können dies tun und erwarten, dass es korrekt funktioniert:

(function(){ 

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

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

})(); 

Der Event-Funktion des Knotens wird „festhalten“ die lokale Variable korrekt, effektiv eine private Variable zu schaffen.

Sie können dies testen in Ihrem Chrome/FF/IE-Konsole:

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); 

Sie sollten das Konsolenprotokoll zwei identische Objekte mit jedem Klick sehen, die jeweils mit a Werte erhöht wird.

Beachten Sie dass die Einstellung n.data zu einem Primitiv wird keine Referenz erstellen. Es kopiert den Wert.

+0

Süße ... das ist, was ich gesucht habe. Es ist also vollkommen in Ordnung, einen Verweis auf das verschachtelte Objekt zu speichern, das an das DOMElement angehängt ist. – Steve

+0

@Steve Ich habe die Spezifikationen in letzter Zeit nicht überprüft. Und ich vermute, dass die Bezugnahme auf das Objekt in der Ereignisbehandlungsroutine in einigen Leuten weniger "gefährlich" ist. Das Anfügen des Objekts direkt an den Knoten * funktioniert jedoch *. Achten Sie nur auf Kollisionen mit eingebauten Attributen - ich denke, die Spezifikation schlägt vor, alle benutzerdefinierten Attribute mit 'x-vendorname-' oder 'data-' zu versehen. ("x-vendor" könnte die Empfehlung für Benutzeragenten sein.) – svidgen

+0

Beachten Sie, dass das Erweitern von DOM-Objekten nur in kontrollierten Umgebungen sicher ist. Hier ist ein großartiger Artikel von Kangax: http: // perfectionkills.com/was ist falsch-mit-erweitern-die-dom/# fehlende_von_spezifikation. – tomekwi

0

Sie können das HTML5-Attribut data- * verwenden, um herauszufinden, welche Zeile es ist. Sie müssen so etwas wie dieses

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()); 

Jetzt fügen wir Ereignis-Listener auf die Schaltfläche tun: -

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

dies ausprobieren !!

Verwandte Themen