Возможно ли в JavaScript получить уникальные ссылки на уникальные элементы DOM (для использования в качестве уникальных ключей в объекте)? - PullRequest
0 голосов
/ 26 января 2019

Пытаясь создать свои собственные методы для двусторонней привязки данных, я подумал, что у меня есть отличная идея.В рамках этой идеи я попытался использовать ссылки на элементы 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?

Ответы [ 3 ]

0 голосов
/ 26 января 2019

Ключи объектов Javascript всегда строки , поэтому, если 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>
0 голосов
/ 26 января 2019

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>
0 голосов
/ 26 января 2019

Вы можете пройти DOM и добавить уникальное имя класса для всего.

j = 0;
for (let i = 0; i < document.body.childNodes.length; i++) {
  document.body.childNodes[i].classList.add("__j" + j++); 
}

Вы захотите сделать это рекурсивно, чтобы получить детей от детей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...