【问题标题】:map nodes to data将节点映射到数据
【发布时间】:2011-06-25 22:33:56
【问题描述】:

我想在数据和 DOM 节点之间建立关联。我尝试直接创建一个Object,以节点为属性,但看起来只使用了节点的字符串表示。

为了使问题更具体,假设我有以下文档,我想将第一个 div 与数字 3 关联,将第二个 div 与列表 ['x', 'y', 'z'] 关联,如何你来做这件事?

<html> <body>
<div/>
<div/>
( 100 more divs )
</body> </html>

我看到 jQuery 有一个 .data() 方法来做这件事。这是唯一的方法吗?这似乎是一个基本的操作,我曾期望使用普通的 javascript 来完成。

目的是向这些节点注册一个 onclick 事件,并准备好数据。

window.onload = function() {
    var index2data = { 0:3, 1:['x', 'y', 'z'] };
    var divs = document.getElementsByTagName("div");
    for(var i = 0; i < divs.length; i++){
        setData( divs[i], index2data[i] )
        divs[i].onclick = onClick;
    }
}

function onClick() {
    var data = getData( this );
    // do a bunch more stuff
}

【问题讨论】:

  • 请停止标记您的标题。很遗憾你已经做了将近两年了!

标签: javascript dom associative-array


【解决方案1】:

您可以设置一个带有 JSON 编码数据的属性。在我提供的示例中,我使用启动 JavaScript 添加数据,但没有理由不应该在您的服务器提供的标记中启用。

然后getData 方法只是读取属性并 JSON 解析它:

function getData(el) {
  return JSON.parse(el.getAttribute('data-stuff'));
}

请注意,我刚刚将 data 属性称为“data-stuff”——因为 data-* 属性是一个有效的 HTML5——显然更恰当地命名它。

没有 jQuery 的工作示例:http://jsbin.com/opugax/edit

使用 jQuery 的工作示例:http://jsbin.com/opugax/2/edit

请注意,如果您不想使用 jQuery,但希望支持 IE7 及以下版本 - 您需要在页面中包含 json2.js:https://github.com/douglascrockford/JSON-js

【讨论】:

  • 一般来说,是否没有反对将数据注入 DOM 的指南?我想将我的数据和 DOM 分开,但似乎这是唯一的方法。这是我将它们分开的尝试,但它不起作用:(jsbin.com/elaxod/4
  • 显然这完全取决于您要解决的问题,但是如果您的数据是特定于 DOM 元素的,如您所建议的,将其附加到 data-foo 属性是完全合法的,但也有道理。您提供的示例不喜欢您使用 DOM 元素作为键,因此它失败了。更多信息 data-* 属性在这里:html5doctor.com/html5-custom-data-attributes
  • 我还应该补充一点——如果你想让你的 DOM 和数据分开,那么它可能表明数据的关键不是 DOM 元素,而是数据应该有一个引用到 DOM(而不是相反)。这显然是将数据链接到 DOM 的更“传统”方式。但是 - 如果你的逻辑是以 DOM 为中心的,它就行不通了 - 这完全取决于你要解决的具体问题 :)
  • 对不起 - 最后的评论!使用 data-* 属性执行此操作的重要因素是服务器可以在标记中传递初始数据。如果这无关紧要 - 那么您不妨使用下面的建议并将任意数据属性附加到 DOM 元素。
  • 谢谢!这是很好的信息。我想它的核心是,我试图将 DOM 节点转换为可散列的东西。在 Python 中我有两种选择,但我在 javascript 中没有看到一个。 docs.python.org/library/functions.html#iddocs.python.org/library/functions.html#hash
【解决方案2】:

为了将实际数据与 DOM 分开,您可以尝试通过脚本为所有元素设置 div ID - 这样做时您应该测试是否有任何 div 已经有 id 并使用它来代替,以免破坏事物...

var obj={};
function setDivIdsAndData(dataToSet)
{
    var divs = document.getElementsByTagName("div");
    for(var i = 0; i < divs.length; i++)
    {
       var divId="d"+i;
       if (divs[i].getAttribute("id")==null)
           divs[i].setAttribute("id",divId);
       else
           divId=divs[i].getAttribute("id");
       obj[divId]=dataToSet[i];
    }
};

现在应用于您的示例案例:

window.onload = function() 
{
    var index2data = { 0:3, 1:['x', 'y', 'z'] };
    setDivIdsAndData(index2data);
};

function onClick() 
{
    var data = obj[this.getAttribute("id")];
    // do a bunch more stuff
};

【讨论】:

  • 如果你想在不使用任何方法处理 div 的情况下这样做,那将更加困难......
  • 你能详细说明一下吗?我不确定我是否理解正确。您是否要将数据放入 div 中?我知道您希望 div 1 的内容是 '3' 而 div 2 是 'xyz'
  • 对不起,我只是误解了你想要的。我在答案中添加了应该满足您需求的内容。
  • 啊,我明白了,再等一下
【解决方案3】:

从技术上讲,这很简单,但我不确定这是否是实现总体目标的最佳方式。

DOM 是可扩展的。

向元素添加数据所需要做的就是将其分配给 DOM 对象,无论是在创建元素时还是之后。下面是一个使用元素 ID 来引用它的示例:

var divObj = document.getElementById('link1');
divObj.data = ['1', '2', '3'];

数据不是元素的 HTML 属性,而是 DOM 的节点扩展,可以保存任何类型的数据,包括函数/方法。

访问和使用这些数据就像在上面分配它一样简单:

var divObj = document.getElementById('link1');
doSomething(divObj.data);

您的目标是使用事件处理程序访问它,这取决于您分配事件的方法。我使用更现代的 obj.addEventListener 和 obj.attachEvent (MSIE)。获取被点击的目标对象和简单的 obj.onclick() 赋值有点不同,但是访问数据是一样的。

【讨论】:

  • 谢谢。我想到了那个解决方案,它确实很好地解决了这个问题,除了它不会打扰任何人来混淆 DOM 和应用程序数据结构吗?我试图将它们分开。
  • 我对 JS 太陌生了,还没有意识到将对象存储在 DOM 中的实际限制,而且我还没有找到任何对此主题有智慧的人。如果您的研究揭示了更好的惯例,请告诉我。
【解决方案4】:

div 节点的集合是一个有序列表——源代码顺序。 使用数组来保存您的数据并为该数据分配相同的索引 div。

var dom= /*[parent]*/.getElementsByTagName('div'),
data= // reference the data array.
L= Math.min(data.length,dom.length),
next;

while(L){
next= data[--L];
if(next!= undefined) dom[L].setAttribute('data-association', next);

【讨论】:

  • 我在执行此操作时遇到了问题。我不明白你使用逗号或next。我还看到一个未关闭的{
猜你喜欢
  • 2012-07-31
  • 2015-07-21
  • 1970-01-01
  • 2013-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-10
  • 1970-01-01
相关资源
最近更新 更多