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

时间:2015-03-10 18:55:56

标签: javascript html dom

我有什么:

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

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

因此a.href是链接,h1包含名称,img.src是图像。

我需要什么:

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

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

如何以这种方式扩展Node类?此外,我不想使用任何框架,只有纯js。谢谢!

1 个答案:

答案 0 :(得分:1)

是否有特定原因要求您扩展DOM?如果没有,您可以定义一个返回所需嵌套属性的函数:

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

否则,这是一篇文章,回答了有关扩展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插件可以定义/操作相同的属性,所以你引入了与其他代码冲突的可能性。