使用JavaScript一次为一个元素设置多个属性


88

如何使用JavaScript一次设置多个属性?不幸的是,我无法在该项目上使用类似jQuery的框架。这是我现在所拥有的:

var elem = document.createElement("img");

elem.setAttribute("src", "http://example.com/something.jpeg");
elem.setAttribute("height", "100%");
elem.setAttribute("width", "100%");

1
@Quantastical使用的答案Object.assign()值得一看,那些不想创建帮助函数的对象-适用于“所有可枚举自己的属性”。
benvc

4
我浏览了所有答案,希望自发布此问题以来的7年中,将会进行某种ES7更新,因此我们不必编写像
@Ariel

Answers:


119

您可以创建一个辅助函数:

function setAttributes(el, attrs) {
  for(var key in attrs) {
    el.setAttribute(key, attrs[key]);
  }
}

这样称呼它:

setAttributes(elem, {"src": "http://example.com/something.jpeg", "height": "100%", ...});

1
好吧,这还不是一次完成,因此不会影响性能。
vsync 2014年

这不是他的要求。我们需要知道如何提高性能
jbartolome,2015年

19
@jbartolome-问题中没有提到“性能”一词。我不知道你从哪里得到这个想法。问题似乎是寻找一种无需多次手动呼叫的方法elem.setAttribute()
jfriend00 '16

我不确定这个问题到底想要什么。可能的理想结果是将attributeChangedCallback称为“仅一次”。如果我需要调用一个依赖于两个属性的函数,通常通常两次调用attributeChangedCallback,每个属性更改调用一次。访问这两个属性的this.getAttribute('your-attr')并在其中一个仍为空的情况下退出是第一个解决方案,但是它不能处理仅设置一个属性而另一个已经具有先前值的情况。但是上帝帮助这实际上不是客观的问题。不容易!
弗拉基米尔·巴西

21

您可能可以使用Object.assign(...)将属性应用于创建的元素。有关更多详细信息,请参见评论。

请记住,heightwidth属性是以像素而不是百分比定义的。您必须使用CSS使其流畅。

var elem = document.createElement('img')
Object.assign(elem, {
  className: 'my-image-class',
  src: 'https://dummyimage.com/320x240/ccc/fff.jpg',
  height: 120, // pixels
  width: 160, // pixels
  onclick: function () {
    alert('Clicked!')
  }
})
document.body.appendChild(elem)

// One-liner:
// document.body.appendChild(Object.assign(document.createElement(...), {...}))
.my-image-class {
  height: 100%;
  width: 100%;
  border: solid 5px transparent;
  box-sizing: border-box
}

.my-image-class:hover {
  cursor: pointer;
  border-color: red
}

body { margin:0 }


1
属性elem.height等是只读的,因此会失败。我查看了描述符,它们是只有getter(未定义的setter)的访问器。
lukeuser

@lukeuser谢谢您的评论。我不知道这些属性是只读的。
用户

2
当您问到“您不能...”的问题时,我可能在您实际上不能做到这一点时问过。
JP Silvashy

2
@JPSilvashy我不打算让我的“你不能只是”像小事一样或表现出优越感。对不起,如果确实如此。老实说,我不确定这是否是一个合适的答案,因为我不是JavaScript忍者,所以我希望像lukeuser这样的人也可以加入进来,以帮助巩固逻辑。
用户

13

如果要使用framework-esq语法(注意:仅IE 8+支持),则可以扩展Element原型并添加自己的setAttributes函数:

Element.prototype.setAttributes = function (attrs) {
    for (var idx in attrs) {
        if ((idx === 'styles' || idx === 'style') && typeof attrs[idx] === 'object') {
            for (var prop in attrs[idx]){this.style[prop] = attrs[idx][prop];}
        } else if (idx === 'html') {
            this.innerHTML = attrs[idx];
        } else {
            this.setAttribute(idx, attrs[idx]);
        }
    }
};

这使您可以使用如下语法:

var d = document.createElement('div');
d.setAttributes({
    'id':'my_div',
    'class':'my_class',
    'styles':{
        'backgroundColor':'blue',
        'color':'red'
    },
    'html':'lol'
});

试试看:http : //jsfiddle.net/ywrXX/1/

如果您不喜欢扩展宿主对象(有些反对)或需要支持IE7-,只需将其用作函数即可

请注意,setAttribute这不适用于styleIE或事件处理程序(无论如何都不应该)。上面的代码处理style,但不处理事件。

文献资料


记录:'Element' is undefined
IE7-

是的,足够公平。忘记了IE7及其COM对象。您可以重载document.createElementdocument.getElementById填充此....,也可以将功能包装在一个函数中。编辑答案以包括该注释
克里斯·贝克

2
更简化的递归版本:的jsfiddle包括IE垫片
Keleko

我真的很喜欢Keleko简化版!唯一的是,在您的版本中,您的JSFiddle中没有innerText。我尝试添加其他if(at [prop] === html){this.innerHTML = set [prop]; },但没有用。我得到一个错误。如何添加innerText设置?
杰西卡

此答案使您可以使用包含元素属性,css属性(可能在嵌套对象中)和innerHTML的单个对象。它还显示了如何使用此修改元素原型(hmmm)或将其用作常规函数(ahhh)。不错的工作!
安德鲁·威廉姆斯

12

您可以创建一个带有可变数量参数的函数:

function setAttributes(elem /* attribute, value pairs go here */) {
    for (var i = 1; i < arguments.length; i+=2) {
        elem.setAttribute(arguments[i], arguments[i+1]);
    }
}

setAttributes(elem, 
    "src", "http://example.com/something.jpeg",
    "height", "100%",
    "width", "100%");

或者,您将属性/值对传递给对象:

 function setAttributes(elem, obj) {
     for (var prop in obj) {
         if (obj.hasOwnProperty(prop)) {
             elem[prop] = obj[prop];
         }
     }
 }

setAttributes(elem, {
    src: "http://example.com/something.jpeg",
    height: "100%",
    width: "100%"
});

您还可以制作自己的可链接对象包装器/方法:

function $$(elem) {
    return(new $$.init(elem));
}

$$.init = function(elem) {
    if (typeof elem === "string") {
        elem = document.getElementById(elem);
    }
    this.elem = elem;
}

$$.init.prototype = {
    set: function(prop, value) {
        this.elem[prop] = value;
        return(this);
    }
};

$$(elem).set("src", "http://example.com/something.jpeg").set("height", "100%").set("width", "100%");

工作示例:http : //jsfiddle.net/jfriend00/qncEz/


11

您可以编写ES5.1辅助函数:

function setAttributes(el, attrs) {
    Object.keys(attrs).forEach(key => el.setAttribute(key, attrs[key]));
}

这样称呼它:

setAttributes(elem, { src: 'http://example.com/something.jpeg', height: '100%' });

5
const setAttributes = (el, attrs) =>
  Object.entries(attrs)
    .forEach(args =>
      el.setAttribute(...args))

4

或创建一个函数来创建一个包含参数中的属性的元素

function elemCreate(elType){
  var element = document.createElement(elType);
  if (arguments.length>1){
    var props = [].slice.call(arguments,1), key = props.shift();
    while (key){ 
      element.setAttribute(key,props.shift());
      key = props.shift();
    }
  }
  return element;
}
// usage
var img = elemCreate('img',
            'width','100',
            'height','100',
            'src','http://example.com/something.jpeg');

仅供参考:height/width='100%'无法使用属性。对于100%的高度/宽度,您需要元素style.height/style.width


@vsync虽然我很感谢您的随意批评和侮辱,但是此答案与此处的其他答案之间没有什么根本的区别。冷静。
克里斯·贝克

@Chris-随机是的,因为我想推广这个答案,所以我不得不在上面的答案上投下反对票。是的,如果您有1000个项目,并且每个项目都必须更改5个属性,那么最好是使用新属性重新创建它们,而不是访问DOM 5000次,您是否同意?
vsync

@vsync如果您使用的是在StackOverflow上发现的随机复制/粘贴功能,而没有考虑有关用例继承的特殊性能,那么您可能会遇到更大的问题。此外,在您投票否决的答案中,将不会访问DOM 5000次,最多只能访问此答案-在两种情况下,有问题的元素都未插入DOM树中。这个答案和我的做同样的事情,我们只是简单地迭代属性。
克里斯·贝克

@Chris-这个问题与我无关。你为什么在谈论我,我在做什么?这无关紧要。如果您需要更改DOM本身上许多节点的属性,您的答案就不是很好,而这个答案会稍好一点,因为它促进了一种很好的思维方式,即您可以重新创建具有所有属性的节点并重新创建节点。将其安装在DOM中。这也不是理想的选择,因为使用该clone方法将是首选。无需从头开始创建整个节点。无论如何,最小化对DOM(最常见的用例)的访问是头等大事。
vsync 2014年

@vsync在抽象意义上使用了“您”一词,并不是将您作为个人(我很确定您是vsynch,我知道),而是给这些答案的假设未来使用者。同样,这两个答案在功能上是相同的。即使您的推理存在缺陷(检查基准),您也可以自由投票选择想要的方式,但是请您对自己的自高自大表示保留。
克里斯·贝克

3

试试这个

function setAttribs(elm, ob) {
    //var r = [];
    //var i = 0;
    for (var z in ob) {
        if (ob.hasOwnProperty(z)) {
            try {
                elm[z] = ob[z];
            }
            catch (er) {
                elm.setAttribute(z, ob[z]);
            }
        }
    }
    return elm;
}

演示:这里


1

使用此功能同时创建和设置属性

function createNode(node, attributes){
    const el = document.createElement(node);
    for(let key in attributes){
        el.setAttribute(key, attributes[key]);
    }
    return el;
}

像这样使用

const input = createNode('input', {
    name: 'test',
    type: 'text',
    placeholder: 'Test'
});
document.body.appendChild(input);

1

我猜这是立即为此类中的任何元素设置属性的最佳方法。

function SetAtt(elements, attributes) {
    for (var element = 0; element < elements.length; element++) {
        for (var attribute = 0; attribute < attributes.length; attribute += 2) {
            elements[element].setAttribute(attributes[attribute], attributes[attribute + 1]);
        }
    }
}
var Class = document.getElementsByClassName("ClassName"); // class array list
var Data = ['att1', 'val1', 'att2', 'val2', 'att3', 'val3']; //attributes array list
SetAtt(Class, Data);

1

您只需在“元素”原型中添加一个方法(setAttributes,末尾带有“ s”),例如:

Element.prototype.setAttributes = function(obj){
  for(var prop in obj) {
    this.setAttribute(prop, obj[prop])
  }
}

您可以在一行中定义它:

Element.prototype.setAttributes = function(obj){ for(var prop in obj) this.setAttribute(prop, obj[prop]) }

您可以像调用其他方法一样正常调用它。属性作为对象给出:

elem.setAttributes({"src": "http://example.com/something.jpeg", "height": "100%", "width": "100%"})

如果给定参数不是对象,则可以添加if语句以引发错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.