Festlegen mehrerer Attribute für ein Element gleichzeitig mit JavaScript

88

Wie kann ich mit JavaScript mehrere Attribute gleichzeitig festlegen? Leider kann ich für dieses Projekt kein Framework wie jQuery verwenden. Folgendes habe ich jetzt:

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

elem.setAttribute("src", "http://example.com/something.jpeg");
elem.setAttribute("height", "100%");
elem.setAttribute("width", "100%");
JP Silvashy
quelle
1
Die Antwort von @Quantastical using Object.assign()ist einen Blick wert für diejenigen, die keine Hilfsfunktion erstellen möchten - funktioniert für "alle aufzählbaren und eigenen Eigenschaften".
Benvc
4
Ich habe alle Antworten durchgeblättert und gehofft, dass es in 7 Jahren, seit diese Frage veröffentlicht wurde, eine Art ES7-Update geben würde, damit wir keine eigene Funktion wie @ Ariels Antwort schreiben müssen
krummens

Antworten:

119

Sie könnten eine Hilfsfunktion erstellen:

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

Nennen Sie es so:

setAttributes(elem, {"src": "http://example.com/something.jpeg", "height": "100%", ...});
Ariel
quelle
1
Nun, es ist auch nicht sofort, also wird es keinen Einfluss auf die Leistung geben.
vsync
Das hat er nicht gefragt. Wir müssen wissen, wie wir die Leistung verbessern können
jbartolome
19
@jbartolome - Das Wort "Leistung" wird in der Frage nicht einmal erwähnt. Ich weiß nicht, woher du diese Vorstellung hast. Die Frage scheint nach einer Möglichkeit zu suchen, nicht elem.setAttribute()mehrmals manuell anrufen zu müssen .
jfriend00
Ich bin mir nicht sicher, was die Frage wirklich will. Ein gut mögliches gewünschtes Ergebnis besteht darin, attributeChangedCallback "nur einmal" aufzurufen. Wenn ich eine Funktion aufrufen muss, die von zwei Attributen abhängt, wird attributeChangedCallback normalerweise zweimal aufgerufen, eines für jede Attributänderung. Der Zugriff auf this.getAttribute ('your-attr') für beide Attribute und das Beenden, wenn eines davon noch leer ist, ist eine erste Lösung, ABER es wird nicht der Fall behandelt, in dem nur ein Attribut festgelegt ist und das andere bereits einen vorherigen Wert hat . Aber Gott hilft, das ist nicht die eigentlich objektive Frage. Nicht einfach!
Vladimir Brasil
21

Möglicherweise können Sie Object.assign(...)Ihre Eigenschaften auf das erstellte Element anwenden. Weitere Details finden Sie in den Kommentaren.

Beachten Sie, dass heightund widthAttribute in Pixel und nicht in Prozent definiert sind. Sie müssen CSS verwenden, um es flüssig zu machen.

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 }

Nutzer
quelle
1
Die Eigenschaften elem.height usw. sind schreibgeschützt, daher schlägt dies fehl. Ich habe mir die Deskriptoren angesehen und sie sind Accessoren mit nur einem Getter (undefinierter Setter).
Lukeuser
@lukeuser Danke für den Kommentar. Ich wusste nicht, dass diese Eigenschaften schreibgeschützt sind.
Benutzer
2
Auf Ihre Frage zu "Könnten Sie nicht einfach ..." habe ich dies wahrscheinlich gestellt, als Sie tatsächlich nicht einfach konnten.
JP Silvashy
2
@JPSilvashy Ich hatte nicht vor, dass mein "Könntest du nicht einfach" als Herabsetzung rüberkommt oder ein Zeichen der Überlegenheit zeigt. Entschuldigung, wenn ja. Ich war mir ehrlich gesagt nicht sicher, ob dies eine geeignete Antwort gewesen wäre, da ich kein JavaScript-Ninja bin, und ich hoffte, dass andere wie lukeuser sich einschalten könnten, um die Logik zu festigen.
Benutzer
13

Wenn Sie eine Framework-esq-Syntax wünschen ( Hinweis: Nur IE 8+ -Unterstützung), können Sie den ElementPrototyp erweitern und Ihre eigene setAttributesFunktion hinzufügen :

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]);
        }
    }
};

Auf diese Weise können Sie die folgende Syntax verwenden:

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

Probieren Sie es aus: http://jsfiddle.net/ywrXX/1/

Wenn Sie ein Host-Objekt nicht gerne erweitern ( einige sind dagegen ) oder IE7- unterstützen müssen, verwenden Sie es einfach als Funktion

Beachten Sie, dass dies in IE oder Ereignishandlern setAttributenicht funktioniert style(sollten Sie sowieso nicht). Der obige Code behandelt styleEreignisse, jedoch keine Ereignisse.

Dokumentation

Chris Baker
quelle
Für die Aufzeichnung: IE7 ->'Element' is undefined
KooiInc
Ja, fair genug. Ich habe IE7 und ihre COM-Objekte vergessen. Sie können dies überladen document.createElementund document.getElementByIdausgleichen ... oder einfach die Funktionalität in eine Funktion einbinden. Die Antwort wurde bearbeitet, um diese Notiz aufzunehmen
Chris Baker,
2
vereinfachte rekursive Version: jsfiddle enthält einen IE Shim
Keleko
Ich mag Keleko vereinfachte Version wirklich! Das einzige ist, dass in Ihrer Version kein innerer Text in Ihrer JSFiddle enthalten ist. Ich habe versucht, else hinzuzufügen, wenn (at [prop] === html) {this.innerHTML = set [prop]; } und es hat nicht funktioniert. Ich bekomme eine Fehlermeldung. Wie kann ich eine innerText-Einstellung hinzufügen?
Jessica
Mit dieser Antwort können Sie ein einzelnes Objekt verwenden, das Elementattribute, CSS-Eigenschaften (möglicherweise in einem verschachtelten Objekt) und innerHTML enthält. Es wird auch gezeigt, wie Sie damit den Elementprototyp (hmmm) ändern oder als normale Funktion (ahhh) verwenden können. Gute Arbeit!
Andrew Willems
12

Sie können eine Funktion erstellen, die eine variable Anzahl von Argumenten akzeptiert:

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%");

Oder Sie übergeben die Attribut / Wert-Paare an ein Objekt:

 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%"
});

Sie können auch Ihren eigenen verkettbaren Objekt-Wrapper / Ihre eigene Methode erstellen:

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%");

Arbeitsbeispiel: http://jsfiddle.net/jfriend00/qncEz/

jfriend00
quelle
11

Sie können eine ES5.1-Hilfsfunktion codieren:

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

Nennen Sie es so:

setAttributes(elem, { src: 'http://example.com/something.jpeg', height: '100%' });
danaktiv
quelle
5
const setAttributes = (el, attrs) =>
  Object.entries(attrs)
    .forEach(args =>
      el.setAttribute(...args))
Geek Devigner
quelle
4

Oder erstellen Sie eine Funktion, die ein Element mit Attributen aus Parametern erstellt

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');

Zu Ihrer Information: height/width='100%'würde nicht mit Attributen funktionieren. Für eine Höhe / Breite von 100% benötigen Sie die Elementestyle.height/style.width

KooiInc
quelle
@vsync Obwohl ich Ihre zufällige Ablehnung und Beleidigung schätze, gibt es hier kaum einen grundlegenden Unterschied zwischen dieser und jeder anderen Antwort. Beruhigen.
Chris Baker
@Chris - es war zufällig ja, weil ich stattdessen diese Antwort bewerben wollte, also musste ich die Antwort darüber herabstimmen. und ja, wenn Sie 1000 Elemente haben und jeweils 5 Attribute ändern müssen, ist es am besten, sie mit den neuen Attributen neu zu erstellen, als 5000 Mal auf das DOM zuzugreifen, würden Sie nicht zustimmen?
vsync
@vsync Wenn Sie eine zufällige Kopier- / Einfügefunktion verwenden, die Sie in StackOverflow gefunden haben, ohne die besondere Leistung zu berücksichtigen, die für Ihren Anwendungsfall gilt, haben Sie wahrscheinlich ein größeres Problem. In der Antwort, die Sie abgelehnt haben, wurde auf das DOM nicht 5000 Mal zugegriffen, nicht mehr als auf diese Antwort. In beiden Fällen wurde das betreffende Element nicht in den DOM-Baum eingefügt. Diese und meine Antwort machen dasselbe, wir iterieren die Eigenschaften einfach anders.
Chris Baker
@ Chris - Diese Frage betrifft mich nicht. Warum redest du über mich und was ich tue oder nicht? es ist irrelevant. Ihre Antwort ist nicht sehr gut, wenn Sie die Attribute vieler Knoten im DOM selbst ändern müssen, während diese Antwort etwas besser ist, weil sie eine gute Denkweise fördert, bei der Sie den Knoten mit all seinen Attributen neu erstellen und neu erstellen Installieren Sie es im DOM. Dies ist auch nicht das Ideal, da die Verwendung der cloneMethode bevorzugt wäre. Sie müssen nicht den gesamten Knoten von Grund auf neu erstellen. Auf jeden Fall ist es oberste Priorität, den Zugriff auf das DOM, den häufigsten Anwendungsfall, zu minimieren.
vsync
@vsync Das Wort "Sie" wird in einem abstrakten Sinne verwendet und bedeutet nicht Sie als Individuum (was Sie, vsynch, ziemlich sicher wissen), sondern für den hypothetischen zukünftigen Verbraucher dieser Antworten. Auch hier sind die beiden Antworten in ihrer Funktion identisch. Sie können frei wählen, wie Sie möchten, auch wenn Ihre Argumentation fehlerhaft ist (überprüfen Sie die Benchmarks), aber behalten Sie Ihre herablassenden Bemerkungen für sich.
Chris Baker
3

Versuche dies

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;
}

DEMO: HIER

Slawe
quelle
1

Verwenden Sie diese Funktion, um Attribute gleichzeitig zu erstellen und festzulegen

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

benutze es so

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

quelle
1

Ich denke, es ist die beste Möglichkeit, Attribute für jedes Element in dieser Klasse gleichzeitig festzulegen.

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);
Dr. JavaB
quelle
1

Sie können dem Prototyp "Element" einfach eine Methode (setAttributes, mit "s" am Ende) hinzufügen, wie:

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

Sie können es in einer Zeile definieren:

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

und Sie können es normal aufrufen, wie Sie die anderen Methoden aufrufen. Die Attribute werden als Objekt angegeben:

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

Sie können eine if-Anweisung hinzufügen, um einen Fehler auszulösen, wenn das angegebene Argument kein Objekt ist.

Soufyane Hedidi
quelle