Menyetel beberapa atribut untuk satu elemen sekaligus dengan JavaScript

90

Bagaimana cara mengatur beberapa atribut sekaligus dengan JavaScript? Sayangnya, saya tidak dapat menggunakan kerangka kerja seperti jQuery pada proyek ini. Inilah yang saya miliki sekarang:

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

elem.setAttribute("src", "http://example.com/something.jpeg");
elem.setAttribute("height", "100%");
elem.setAttribute("width", "100%");
JP Silvashy
sumber
1
Jawaban dari @Quantastical use Object.assign()patut untuk dicoba bagi mereka yang tidak ingin membuat fungsi helper - berfungsi untuk "semua properti enumerable dan memiliki ".
benvc
4
Saya menelusuri semua jawaban, berharap dalam 7 tahun sejak pertanyaan ini diposting akan ada semacam pembaruan ES7, sehingga kami tidak perlu menulis fungsi kami sendiri seperti jawaban @ Ariel
krummens

Jawaban:

121

Anda bisa membuat fungsi pembantu:

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

Sebut saja seperti ini:

setAttributes(elem, {"src": "http://example.com/something.jpeg", "height": "100%", ...});
Ariel
sumber
1
yah itu tidak sekaligus juga, jadi tidak akan ada pengaruhnya terhadap performa.
vsync
Ini bukan yang dia minta. Kami perlu tahu cara meningkatkan kinerja
jbartolome
19
@jbartolome - Kata "kinerja" tidak disebutkan sekali dalam pertanyaan. Saya tidak tahu dari mana Anda mendapatkan gagasan itu. Pertanyaan itu tampaknya mencari cara agar tidak perlu menelepon elem.setAttribute()berkali-kali secara manual .
jfriend00
Saya tidak yakin pertanyaan apa yang sebenarnya diinginkan. Kemungkinan hasil yang diinginkan adalah memanggil atributChangedCallback "hanya sekali". Jika saya perlu memanggil fungsi yang bergantung pada dua atribut, biasanya attributeChangedCallback dipanggil dua kali, satu untuk setiap perubahan atribut. Mengakses this.getAttribute ('your-attr') untuk kedua atribut dan keluar jika salah satunya masih kosong adalah solusi pertama TETAPI tidak menangani kasus di mana hanya satu atribut yang disetel, dan yang lainnya sudah memiliki nilai sebelumnya . Tapi Tuhan membantu ini bukanlah pertanyaan yang sebenarnya objektif. Tidak mudah!
Vladimir Brasil
23

Anda mungkin dapat menggunakan Object.assign(...)untuk menerapkan properti Anda ke elemen yang dibuat. Lihat komentar untuk detail tambahan.

Perlu diingat bahwa atribut heightdan ditentukan dalam piksel , bukan persen. Anda harus menggunakan CSS untuk membuatnya berubah-ubah.width

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 }

pengguna
sumber
1
Properti, elem.height dll., Adalah hanya-baca, jadi ini gagal. Saya melihat deskriptornya, dan mereka adalah pengakses dengan hanya pengambil (penyetel tidak ditentukan).
Lukeuser
@lukeuser Terima kasih atas komentarnya. Saya tidak tahu bahwa properti itu hanya-baca.
pengguna
2
Untuk pertanyaan Anda tentang "tidak bisakah Anda ..." Saya menanyakan hal ini mungkin ketika Anda sebenarnya tidak bisa.
JP Silvashy
2
@JPSilvashy Saya tidak bermaksud untuk "tidak bisakah Anda" dianggap meremehkan atau menunjukkan tanda superioritas. Maaf jika ya. Sejujurnya saya tidak yakin apakah ini akan menjadi jawaban yang cocok karena saya bukan ninja JavaScript, jadi saya berharap orang lain seperti Lukeuser dapat ikut membantu memperkuat logika.
pengguna
13

Jika Anda menginginkan sintaks framework-esq ( Catatan: hanya dukungan IE 8+), Anda dapat memperluas Elementprototipe dan menambahkan setAttributesfungsi Anda sendiri :

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

Ini memungkinkan Anda menggunakan sintaks seperti ini:

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

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

Jika Anda tidak suka memperluas objek host ( ada yang menentang ) atau perlu mendukung IE7-, gunakan saja sebagai fungsi

Perhatikan bahwa setAttributeitu tidak akan berfungsi styledi IE, atau penangan acara (Anda tidak seharusnya melakukannya). Kode di atas menangani style, tetapi bukan peristiwa.

Dokumentasi

Chris Baker
sumber
Sebagai catatan: IE7 ->'Element' is undefined
KooiInc
Ya, cukup adil. Lupa tentang IE7 dan objek COM mereka. Anda dapat membebani document.createElementdan document.getElementByIdmengabaikan ini .... atau hanya membungkus fungsionalitas dalam sebuah fungsi. Jawaban yang diedit untuk memasukkan catatan itu
Chris Baker
2
versi rekursif yang lebih sederhana: jsfiddle menyertakan IE shim
Keleko
Saya sangat suka versi sederhana Keleko! Satu-satunya hal adalah, dalam versi Anda, tidak ada teks dalam di JSFiddle Anda. Saya mencoba menambahkan yang lain jika (di [prop] === html) {this.innerHTML = set [prop]; } dan tidak berhasil. Saya mendapatkan kesalahan. Bagaimana cara menambahkan pengaturan innerText?
Jessica
Jawaban ini memungkinkan Anda menggunakan satu objek yang berisi atribut elemen, properti css (berpotensi dalam objek bersarang), dan innerHTML. Ini juga menunjukkan bagaimana menggunakan ini memodifikasi prototipe elemen (hmmm) atau menggunakannya sebagai fungsi normal (ahhh). Pekerjaan yang baik!
Andrew Willems
12

Anda dapat membuat fungsi yang menggunakan sejumlah variabel argumen:

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

Atau, Anda meneruskan pasangan atribut / nilai pada sebuah objek:

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

Anda juga bisa membuat pembungkus / metode objek yang dapat dirantai sendiri:

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

Contoh kerja: http://jsfiddle.net/jfriend00/qncEz/

jfriend00
sumber
12

Anda dapat membuat kode fungsi pembantu ES5.1:

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

Sebut saja seperti ini:

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

Atau buat fungsi yang membuat elemen termasuk atribut dari parameter

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

FYI: height/width='100%'tidak akan berfungsi menggunakan atribut. Untuk tinggi / lebar 100% Anda membutuhkan elemenstyle.height/style.width

KooiInc
sumber
@vsync Meskipun saya menghargai downvote dan penghinaan acak Anda, ada sedikit perbedaan mendasar antara jawaban ini dan jawaban lainnya di sini. Tenang.
Chris Baker
@ Chris - itu acak ya, karena saya ingin mempromosikan jawaban ini, jadi saya harus memberi suara negatif untuk jawaban di atasnya. dan ya, jika Anda memiliki 1000 item dan Anda harus mengubah 5 atribut untuk masing-masing item, akan lebih baik jika Anda membuatnya kembali dengan atribut baru daripada mengakses DOM 5000 kali, tidakkah Anda setuju?
vsync
@vsync jika Anda menggunakan fungsi salin / tempel acak yang Anda temukan di StackOverflow tanpa mempertimbangkan kinerja khusus terkait yang diwariskan ke kasus penggunaan Anda, maka Anda mungkin memiliki masalah yang lebih besar. Lebih lanjut, dalam jawaban yang Anda pilih, DOM tidak akan diakses 5000 kali, tidak lebih dari jawaban ini - dalam kedua kasus, elemen yang dimaksud belum dimasukkan ke dalam pohon DOM. Jawaban ini dan milik saya melakukan hal yang sama, kami hanya mengulang properti secara berbeda.
Chris Baker
@ Chris - Pertanyaan ini bukan urusan saya. mengapa Anda berbicara tentang saya dan apa yang saya lakukan atau tidak? itu tidak relevan. Jawaban Anda tidak terlalu baik jika seseorang perlu mengubah banyak atribut node di DOM itu sendiri, sementara jawaban ini sedikit lebih baik karena mempromosikan cara berpikir yang baik, di mana Anda membuat ulang node dengan semua atributnya dan kembali instal di DOM. Ini juga bukan yang ideal, karena menggunakan clonemetode ini lebih disukai. Tidak perlu membuat seluruh node dari awal. Bagaimanapun, itu prioritas utama untuk meminimalkan akses ke DOM, kasus penggunaan paling umum.
vsync
@vsync Kata "Anda" digunakan dalam arti abstrak, bukan berarti Anda sebagai individu (yang saya yakin Anda, vsynch, tahu) tetapi untuk konsumen hipotesis masa depan dari jawaban-jawaban ini. Sekali lagi, kedua jawaban itu identik fungsinya. Anda bebas memilih sesuka Anda, meskipun alasan Anda salah (periksa tolok ukur), tetapi simpan komentar merendahkan untuk diri Anda sendiri.
Chris Baker
3

Coba ini

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: DI SINI

Slawe
sumber
2

Anda cukup menambahkan metode (setAttributes, dengan "s" di akhir) ke prototipe "Elemen" seperti:

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

Anda dapat menentukannya dalam satu baris:

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

dan Anda dapat memanggilnya seperti biasa saat memanggil metode lain. Atribut diberikan sebagai objek:

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

Anda bisa menambahkan pernyataan if untuk membuat kesalahan jika argumen yang diberikan bukan objek.

Soufyane Hedidi
sumber
Sekarang masuk akal. Saya bertanya-tanya bagaimana melakukan perubahan semacam ini ke fungsi yang telah ditentukan sebelumnya. Terima kasih!
testing_22
1

gunakan fungsi ini untuk membuat dan menyetel atribut pada saat yang bersamaan

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

gunakan seperti itu

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

sumber
1

Saya kira itu cara terbaik untuk mengatur atribut sekaligus untuk setiap elemen di kelas ini.

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
sumber