javascript 如何将对象与 DOM 元素关联
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16113070/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Associate an Object with a DOM Element
提问by Steve
I have a master object in my JS setup, i.e.:
我的 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
}
]
}
Now I loop over my cars and put them in a table. In the table I also have a button that lets me toggle the car as "in use" and "not in use".
现在我把我的车翻过来放在一张桌子上。在表格中,我还有一个按钮,可让我将汽车切换为“使用中”和“未使用”。
How can I associate the DOM Element of every row with its corresponding car, so that if I toggle the "inuse" flag, I can update the master object?
如何将每一行的 DOM 元素与其对应的汽车相关联,以便如果我切换“inuse”标志,我可以更新主对象?
采纳答案by Steve
I'd suggest considering addEventListener
, and a constructor that conforms your objects to the eventListener
interface.
我建议考虑addEventListener
,以及一个使您的对象符合eventListener
接口的构造函数。
That way you can have a nice association between your object, your element, and its handlers.
这样你就可以在你的对象、你的元素和它的处理程序之间建立一个很好的关联。
To do this, make a constructor that's specific to your data.
为此,请创建一个特定于您的数据的构造函数。
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);
}
Then implement the interface:
然后实现接口:
Car.prototype.handleEvent = function(e) {
switch (e.type) {
case "click": this.click(e);
// add other event types if needed
}
}
Then implement your .click()
handler on the prototype.
然后.click()
在原型上实现您的处理程序。
Car.prototype.click = function(e) {
// do something with this.element...
this.element.style.color = "#F00";
// ...and the other properties
this.inuse = !this.inuse
}
So then you can just loop over the Array, and make a new Car
object for each item, and it'll create the new element and add the listener(s).
那么你可以循环遍历数组,Car
为每个项目创建一个新对象,它会创建新元素并添加侦听器。
myGarage.cars.forEach(function(obj) {
new Car(obj)
})
回答by svidgen
You can actually attach an object directly to a node:
您实际上可以将对象直接附加到节点:
var n = document.getElementById('green-ford-escape');
n.carObject = myGarage.cars[0];
n.onclick = function() {
doSomethingWith(this.carObject);
}
For the same of removing ambiguity, in some cases, it's more clear write the above event handler to refer to n
instead of this
:
为了消除歧义,在某些情况下,编写上述事件处理程序来引用n
而不是this
:
n.onclick = function() {
doSomethingWith(n.carObject);
}
You can also refer directly to the object from the attached event:
您还可以从附加事件中直接引用对象:
var n = document.getElementById('green-ford-escape');
n.onclick = function() {
doSomethingWith(myGarage.cars[0]);
}
In the latter case, myGarage
does nothave to be global. You can do this and expect it to work correctly:
在后一种情况下,myGarage
也没有必须是全球性的。您可以这样做并期望它正常工作:
(function(){
var myGarage = { /* ... etc ... */ };
var n = document.getElementById('green-ford-escape');
n.onclick = function() {
doSomethingWith(myGarage.cars[0]);
}
})();
The node's event function will "hold onto" the local variable correctly, effectively creating a private variable.
节点的事件函数将正确“保持”局部变量,有效地创建一个私有变量。
You can test this in your Chrome/FF/IE console:
您可以在 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);
You should see the console log two identical objects with each click, each with incrementing a
values.
您应该会看到控制台在每次单击时记录两个相同的对象,每个对象的a
值都在递增。
Bewarethat setting n.data
to a primitive will not create a reference. It'll copy the value.
请注意,设置n.data
为基元不会创建引用。它会复制值。
回答by sachinjain024
You can use HTML5 data-* attribute to find out which row it is. You must be doing something like this
您可以使用 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());
Now we will add event listener on button :-
现在我们将在按钮上添加事件侦听器:-
$('.toggle-inuse').click(function() {
var i = $(this).data('carId');
myGarbage.cars[i].inuse = !myGarbage.cars[i].inuse; //Wow done
}
Try this out !!
试试这个!!
回答by AlbertEngelB
You'll want some sort of ID or distinct row in your information, else you'll have to rely on the array index to do this. Either way you'll want to store the data using data attributes.
您需要在您的信息中使用某种 ID 或不同的行,否则您将不得不依赖数组索引来执行此操作。无论哪种方式,您都希望使用数据属性来存储数据。
So when you loop through:
所以当你循环时:
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>'
}
And on your click event:
在您的点击事件中:
$('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;
})
If you bind the data to the DOM, you may not even need to update the actual JS data. Could go over each row in the table and re-create the data-object you created the table from.
如果将数据绑定到 DOM,您甚至可能不需要更新实际的 JS 数据。可以查看表中的每一行并重新创建您从中创建表的数据对象。