扩展 DOM 元素添加自定义变量(如在输入节点中)

Extending DOM elements adding custom variables (like in input nodes)

我有:

基本由主要数据点组成的组列表:link、名称和封面图像。每个组的代码如下所示:

<a href="/group/ololo" class="group-item">
    <h1>Group Name</h1>
    <img src="path/to/the/image.png" />
</a>

因此a.href是link,h1是名字,img.src是图片。

我需要的:

我需要为每个组创建一个模型表示,以便我可以简单地使用 group.link、group.name 和 group.image 访问它。

我考虑用构造函数创建一个 class 并手动设置所有字段,它实际上可以工作。我想要做的是扩展节点 class 以将这些字段添加到对象,如果我正在尝试访问 a.group-item。我想要的一个示例是特殊节点,例如具有 .value 变量的 input[type=text] 或具有 .checked 变量的 input[type=checkbox]。

如何以这种方式扩展节点 class?另外,我不想为此使用任何框架,只使用纯 js。谢谢!

您想延长 DOM 有什么具体原因吗?如果没有,您可以只定义一个函数,该函数 returns 您想要的嵌套属性:

var group = document.getElementsByClassName('group-item');

var items = Array.prototype.map.call(group, item);

function item(element) {
    return {
        link: element.href,
        name: element.getElementsByTagName('h1')[0].innerText,
        image: element.getElementsByTagName('img')[0].src
    };
}

http://jsbin.com/xidufiyara/1/edit?html,js,console

否则,这里有一个 post 可以回答您关于扩展 DOM 的问题:In Javascript, can you extend the DOM?

编辑:这是使用 Object.defineProperty 的解决方案:

function configureGroupItem(groupItem) {
    Object.defineProperty(groupItem, 'link', {
      enumerable: true,
      get: function() {
        return groupItem.href;
      }
    });

    Object.defineProperty(groupItem, 'name', {
      enumerable: true,
      get: function() {
        return groupItem.getElementsByTagName('h1')[0].innerText;
      },
      set: function(val) {
        groupItem.getElementsByTagName('h1')[0].innerText = val
      }
    });

    Object.defineProperty(groupItem, 'image', {
      enumerable: true,
      get: function() {
        return groupItem.getElementsByTagName('img')[0].src;
      },
      set: function(val) {
        groupItem.getElementsByTagName('img')[0].src = val
      }
    });
}

以下是我应用和使用属性的方式:

var group = document.getElementsByClassName('group-item');

Array.prototype.map.call(group, configureGroupItem);

for (var i = 0; i < group.length; ++i) {
  var item = group[i]

  // set item name
  item.name = 'Group' + i

  // set item image
  item.image = 'http://placehold.it/' + (i+4) + '0x' + (i+2) + '0'

  // print the data
  console.log(item.name + ' ' + item.image + ' ' + item.link)
}

当然,这与旧版浏览器不兼容。不鼓励这样做的另一个原因是因为其他库/javascript 插件可以定义/操作相同的属性,所以你引入了与其他代码冲突的可能性。