Как связать объект с элементом DOM
У меня есть главный объект в моей настройке 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", я могу обновить главный объект?
Ответы
Ответ 1
Я бы предложил рассмотреть 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
}
Итак, вы можете просто перебрать Array и создать новый объект Car
для каждого элемента, и он создаст новый элемент и добавит слушателя (ов).
myGarage.cars.forEach(function(obj) {
new Car(obj)
})
Ответ 2
Фактически вы можете прикреплять объект непосредственно к node:
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]);
}
})();
Функция события node корректно "удерживает" локальную переменную, эффективно создавая закрытую переменную.
Вы можете протестировать это в консоли 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
.
Остерегайтесь, что установка n.data
для примитива не создаст ссылку. Он скопирует значение.
Ответ 3
Вам понадобится какой-то идентификатор или отдельная строка в вашей информации, иначе вам придется полагаться на индекс массива, чтобы сделать это. В любом случае вы захотите сохранить данные с помощью атрибутов данных.
Итак, когда вы переходите через:
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>'
}
И в событии click:
$('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;
})
Если вы привязываете данные к DOM, вам может даже не понадобиться обновлять фактические данные JS. Можно перебирать каждую строку в таблице и воссоздавать объект данных, из которого вы создали таблицу.
Ответ 4
Вы можете использовать атрибут data5 * HTML5, чтобы узнать, какая строка это. Вы должны делать что-то вроде этого
var table = $('<table>'); // Let 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
}
Попробуйте это!