JavaScript ile aynı anda bir öğe için birden çok özellik ayarlama


90

JavaScript ile aynı anda birden çok özelliği nasıl ayarlayabilirim? Maalesef bu projede jQuery gibi bir çerçeve kullanamıyorum. İşte şimdi sahip olduğum şey:

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

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

1
@Quantastical tarafından verilen yanıt Object.assign(), yardımcı bir işlev oluşturmak istemeyenler için bir göz atmaya değer - "tüm numaralandırılabilir ve kendi özellikleri" için çalışır.
benvc

4
Bu sorunun gönderilmesinden bu yana 7 yıl içinde bir çeşit ES7 güncellemesi olacağını umarak tüm yanıtları kaydırdım, bu yüzden @ Ariel'in cevabı
krummens

Yanıtlar:


121

Yardımcı bir işlev yapabilirsiniz:

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

Şöyle diyelim:

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

1
aynı zamanda aynı zamanda değil, dolayısıyla performans üzerinde hiçbir etkisi olmayacaktır.
vsync

İstediği bu değildi. Performansı nasıl iyileştireceğimizi bilmemiz gerekiyor
jbartolome

19
@jbartolome - "Performans" kelimesi soruda bir kez geçmiyor. Bu fikri nereden aldığını bilmiyorum. Soru, elem.setAttribute()birden çok kez manuel olarak aramak zorunda kalmamak için bir yol arıyor gibi görünüyor .
jfriend00

Sorunun gerçekten ne istediğinden emin değilim. İyi bir olası sonuç, attributeChangedCallback'i "yalnızca bir kez" çağırmaktır. İki özniteliğe bağlı bir işlevi çağırmam gerekirse, genellikle attributeChangedCallback, her öznitelik değişikliği için bir tane olmak üzere iki kez çağrılır. Her iki öznitelik için this.getAttribute'a ('your-attr') erişmek ve bunlardan biri hala boşsa çıkmak ilk çözümdür ANCAK yalnızca bir özniteliğin ayarlandığı ve diğerinin zaten önceki bir değere sahip olduğu durumu işlemez . Ancak Tanrı yardım eder, sorunun aslında objektif olmamasıdır. Kolay değil!
Vladimir Brasil

23

Object.assign(...)Özelliklerinizi oluşturulan öğeye uygulamak için kullanabilirsiniz . Ek ayrıntılar için yorumlara bakın.

Unutmayın heightve widthöznitelikleri piksel olarak tanımlanan değil, yüzdeleri. Akıcı hale getirmek için CSS kullanmanız gerekecek.

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
Özellikler, elem.height vb. Salt okunurdur, bu nedenle bu başarısız olur. Tanımlayıcılara baktım ve bunlar sadece alıcıya sahip erişimciler (tanımsız ayarlayıcı).
lukeuser

@lukeuser Yorumunuz için teşekkürler. Bu özelliklerin salt okunur olduğunu bilmiyordum.
kullanıcı

2
"Sadece yapamaz mısın ..." hakkındaki sorunuza, bunu muhtemelen tam olarak yapamadığınızda sordum.
JP Silvashy

2
@JPSilvashy "Yapamaz mısın" diyerek küçümseyici görünmeye veya bir üstünlük belirtisi göstermeye niyetim yoktu. Olduysa özür dilerim. JavaScript ninja olmadığım için bunun uygun bir cevap olup olmayacağından gerçekten emin değildim, bu yüzden lukeuser gibi diğerlerinin mantığı sağlamlaştırmaya yardımcı olmasını umuyordum.
kullanıcı

13

Framework-esq sözdizimi istiyorsanız ( Not: yalnızca IE 8+ desteği), Elementprototipi genişletebilir ve kendi setAttributesişlevinizi ekleyebilirsiniz :

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

Bu, aşağıdaki gibi sözdizimini kullanmanıza izin verir:

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

Deneyin: http://jsfiddle.net/ywrXX/1/

Bir ana bilgisayar nesnesini genişletmekten hoşlanmıyorsanız ( bazıları karşıttır ) veya IE7'yi desteklemeniz gerekiyorsa, onu bir işlev olarak kullanın

setAttributeBunun styleIE'de veya olay işleyicilerinde çalışmayacağını unutmayın (yine de yapmamalısınız). Yukarıdaki kod styleolayları yönetir , ancak olayları ele almaz.

Dokümantasyon


Kayıt için: IE7 ->'Element' is undefined
KooiInc

Evet, yeterince adil. IE7'yi ve COM nesnelerini unuttum. Aşırı yükleyebilir document.createElementve document.getElementByIdbunu değiştirebilirsin .... ya da sadece işlevselliği bir fonksiyona sarabilirsiniz. Cevap bu notu içerecek şekilde düzenlendi
Chris Baker

2
daha basitleştirilmiş özyinelemeli sürüm: jsfiddle bir IE altlığı içerir
Keleko

Keleko'nun basitleştirilmiş versiyonunu gerçekten seviyorum! Sizin sürümünüzde tek şey, JSFiddle'ınızda bir innerText olmaması. Başka if eklemeyi denedim ([prop] === html'de) {this.innerHTML = set [prop]; } ve işe yaramadı. Bir hata alıyorum. İç Metin ayarını nasıl ekleyebilirim?
Jessica

Bu yanıt, öğe niteliklerini, css özelliklerini (potansiyel olarak iç içe geçmiş bir nesnede) ve innerHTML içeren tek bir nesneyi kullanmanıza izin verir. Ayrıca bunun nasıl kullanılacağını, eleman prototipini (hmmm) nasıl değiştireceğinizi veya normal bir işlev olarak (ahhh) nasıl kullanacağınızı gösterir. İyi iş!
Andrew Willems

12

Değişken sayıda argüman alan bir işlev oluşturabilirsiniz:

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

Veya öznitelik / değer çiftlerini bir nesneye iletirsiniz:

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

Ayrıca kendi zincirlenebilir nesne sarmalayıcınızı / yönteminizi de yapabilirsiniz:

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

Çalışma örneği: http://jsfiddle.net/jfriend00/qncEz/


12

Bir ES5.1 yardımcı işlevi kodlayabilirsiniz:

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

Şöyle diyelim:

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

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

4

Veya parametrelerden öznitelikler içeren bir öğe oluşturan bir işlev oluşturun

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

Bilginize: height/width='100%'öznitelikler kullanılarak çalışmaz. % 100 yükseklik / genişlik için elemanlara ihtiyacınız varstyle.height/style.width


@vsync Rastgele olumsuz oyunuzu ve hakaretinizi takdir etmeme rağmen, bununla buradaki diğer cevaplar arasında çok az temel fark var. Sakin ol.
Chris Baker

@Chris - rastgele bir evetti, çünkü bunun yerine bu cevabı tanıtmak istedim, bu yüzden yukarıdaki cevaba olumsuz oy vermek zorunda kaldım. ve evet, 1000 öğeniz varsa ve her biri için 5 özniteliği değiştirmeniz gerekiyorsa, DOM'a 5000 kez erişmek yerine bunları yeni özniteliklerle yeniden oluşturmak en iyisi olur, kabul etmiyor musunuz?
vsync

@vsync StackOverflow'da bulduğunuz rastgele bir kopyala / yapıştır işlevini, kullanım durumunuza ilişkin özel performans mirasını dikkate almadan kullanıyorsanız, muhtemelen daha büyük bir sorununuz var demektir. Ayrıca, olumsuz oy verdiğiniz yanıtta, DOM'a 5000 kez erişilemezdi, bu yanıttan fazla değil - her iki durumda da söz konusu öğe DOM ağacına eklenmemiştir. Bu cevap ve benimki aynı şeyi yapıyor, sadece özellikleri farklı şekilde yineliyoruz.
Chris Baker

@Chris - Bu soru beni ilgilendirmiyor. neden benim hakkımda konuşuyorsun ve ben ne yapıyorum ya da yapmıyorum? alakasız. DOM'un kendisindeki birçok düğümün özniteliğini değiştirmek gerektiğinde yanıtınız pek iyi değildir, ancak bu yanıt biraz daha iyidir, çünkü düğümü tüm öznitelikleriyle yeniden oluşturduğunuz ve yeniden oluşturduğunuz iyi bir düşünme biçimini teşvik eder. DOM'a yükleyin. Bu aynı zamanda ideal değildir, çünkü cloneyöntemi kullanmak tercih edilir. Tüm düğümü sıfırdan oluşturmaya gerek yok. Her neyse, en yaygın kullanım örneği olan DOM'a erişimi en aza indirmek en önemli önceliktir.
vsync

@vsync "Siz" kelimesi soyut bir anlamda kullanılıyor, sizi bir birey olarak değil (ki eminim siz, vsynch, biliyorum) değil, bu yanıtların varsayımsal gelecekteki tüketicisi için. Bir kez daha, iki cevap işlev açısından aynıdır. Muhakemeniz kusurlu olsa bile (kriterleri kontrol edin), istediğiniz şekilde oy kullanmakta özgürsünüz, ancak küçümseyici sözlerinizi kendinize saklayın.
Chris Baker

3

Bunu dene

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: BURADA


2

"Element" prototipine basitçe bir yöntem (sonunda "s" bulunan setAttributes) ekleyebilirsiniz:

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

tek satırda tanımlayabilirsiniz:

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

ve diğer yöntemleri çağırdığınızda normal olarak çağırabilirsiniz. Nitelikler bir nesne olarak verilmiştir:

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

Verilen bağımsız değişken bir nesne değilse, bir hata atmak için bir if ifadesi ekleyebilirsiniz.


Şimdi bir şey ifade ediyor. Önceden tanımlanmış bir işleve bu tür bir değişikliği nasıl yapacağımı merak ediyordum. Teşekkürler!
test_22

1

Bu işlevi aynı anda özellikler oluşturmak ve ayarlamak için kullanın

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

öyle kullan

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

1

Sanırım bu sınıftaki herhangi bir öğe için öznitelikleri bir kerede ayarlamanın en iyi yolu bu.

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);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.