在尝试创建自己的双向数据绑定方法时,我认为我有个好主意。作为该想法的一部分,我尝试使用DOM元素引用作为JavaScript对象中的键,该对象将保存与每个元素相关的数据。
不幸的是,似乎JavaScript对DOM元素的引用是通用的(关于tagName [如p])。
例如:
function testScenarios(){
// create references to DOM objects
var a = document.getElementById("id_a"),
b = document.getElementById("id_b");
// create and fill a test object
var testObj = {};
testObj[a] = "a"; // use the reference to p#id_a as a key for the value "a"
testObj[b] = "b"; // use the reference to p#id_b as a key for the value "b"
testObj[a.id] = "aId"; // use the id captured from the reference to p#id_a as a key for the value "aID"
testObj[b.id] = "bId"; // use the id captured from reference to p#id_b as a key for the value "bId"
testObj["0"] = a; // use "0" as a key for a value that is the reference to p#id_a
testObj["1"] = b; // use "1" as a key for a value that is the reference to p#id_b
// store test values
var testResults = {
does_a_equal_b : (a===b),
does_aId_equal_bId : (a.id===b.id),
does_objA_equal_objB : (testObj[a]===testObj[b]),
does_objAid_equal_objBid : (testObj[a.id]===testObj[b.id]),
does_obj0_equal_obj1 : (testObj["0"]===testObj["1"]),
what_is_a : a,
what_is_b : b
}
// run the tests and display results
for(testKey in testResults){
document.getElementById(testKey).innerHTML = testResults[testKey];
}
document.getElementById("the_object").innerHTML = JSON.stringify(testObj, null, 4);
}
p {width:400px;}
p:nth-child(odd){background:#ccc;}
span {float:right; font-weight:800;}
p:nth-child(8){background:#c63;}
p:nth-child(10){background:#c63; height:40px;}
p:nth-child(11){background:#c63; height:40px;}
p:nth-child(12){background:#c63; height:60px;}
<p id="id_a">paragraph element a</p>
<p id="id_b">paragraph element b</p>
<button onclick="testScenarios()">Run the tests</button>
<p>a === b? (expecting false)<span id="does_a_equal_b"></span></p>
<p>a.id === b.id? (expecting false)<span id="does_aId_equal_bId"></span></p>
<p>testObj[a.id] === testObj[b.id]? (expecting false)<span id="does_objAid_equal_objBid"></span></p>
<p>testObj["0"] === testObj["1"]? (expecting false)<span id="does_obj0_equal_obj1"></span></p>
<p>testObj[a] === testObj[b]? (expecting false)<span id="does_objA_equal_objB"></span></p>
<p>ok, but... why?</p>
<p>What is a? (expecting somethihng like p#id_a, or a number)<span id="what_is_a"></span></p>
<p>What is b? (expecting somethihng like p#id_a, or a number)<span id="what_is_b"></span></p>
<p>What is testObj?<span id="the_object"></span></p>
<p>Sooooo... even though:<br>a !== b,<br>testObj[a] === testObj[b].<br>?¯\_(ツ)_/¯?<br><br>Is there some way to get the unique aspects of references a and b out of those references for later use?</p>
是否有一种方法来获取与对DOM对象的每次引用相关联的唯一标识符?
答案 0 :(得分:1)
JavaScript对象键始终是 strings ,因此,如果a
是元素,testObj[a]
将不起作用,因为该元素将被强制转换为字符串,这可能与其他元素的强制字符串具有相同的值。请改用Map
,它类似于对象,但是可以具有任何值的键,包括HTMLElements
// create references to DOM objects
var a = document.getElementById("id_a"),
b = document.getElementById("id_b");
// create and fill a test object
const map = new Map();
map.set(a, 'a');
map.set(b, 'b');
map.set(a.id, "aId");
map.set(b.id, "bId");
map.set('0', a);
map.set('1', b);
map.set(a.id, "aId");
// store test values
var testResults = {
does_a_equal_b: (a === b),
does_aId_equal_bId: (a.id === b.id),
does_objA_equal_objB: (map.get(a) === map.get(b)),
does_objAid_equal_objBid: (map.get(a.id) === map.get(b.id)),
does_obj0_equal_obj1: (map.get('0') === map.get('1')),
what_is_a: a,
what_is_b: b
};
console.log(testResults);
<p id="id_a">paragraph element a</p>
<p id="id_b">paragraph element b</p>
答案 1 :(得分:1)
WeakMap确实很方便。
与Map相似,但是在元素被破坏时将被删除并收集垃圾。
下面是一个简单的工作片段。出于测试目的,我只是创建一个附加到元素的简单生成的字符串。然后从点击处理程序中,我正在读回此信息。对于更复杂的数据结构,该值也可以是对象。
const data = new WeakMap();
let count = 0;
for (const el of document.querySelectorAll("div")) {
count += 1;
data.set(el, `This is data for item ${count}`);
}
document.body.addEventListener("click", evt => {
const info = data.get(evt.target);
if (info) document.querySelector("#clicked").innerText = info;
});
div {
border: 1px solid black;
padding: 4px;
margin: 4px;
}
<div id="items">
<div>one</div>
<div>two</div>
<div>three</div>
<div>four</div>
</div>
<div id="clicked"></div>
答案 2 :(得分:0)
您可以遍历DOM并为所有内容添加唯一的类名。
j = 0;
for (let i = 0; i < document.body.childNodes.length; i++) {
document.body.childNodes[i].classList.add("__j" + j++);
}
您将要递归地这样做,以生下孩子。