Встановлення кількох атрибутів для елемента одночасно за допомогою 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 using Object.assign()варто шукати тим, хто не хоче створювати допоміжну функцію - працює для "всіх перелічених та власних властивостей".
benvc,

4
Я прокрутив всі відповіді, сподіваючись, що через 7 років після публікації цього питання відбудеться якесь оновлення ES7, завдяки чому нам не доведеться писати власну функцію, як відповідь @ Ariel
krummens

Відповіді:


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

Це не те, що він просив. Ми повинні знати, як покращити ефективність
jbartolome

19
@jbartolome - Слово "виступ" не згадується жодного разу у питанні. Я не знаю, звідки ти взяв це поняття. Питання, схоже, шукає спосіб, як не доведеться вручну телефонувати elem.setAttribute()кілька разів.
jfriend00

Я не впевнений, чого насправді хоче запитання. Хорошим можливим бажаним результатом є виклик attributeChangedCallback "лише один раз". Якщо мені потрібно викликати функцію, яка залежить від двох атрибутів, зазвичай attributeChangedCallback викликається двічі, по одному для кожної зміни атрибута. Доступ до this.getAttribute ('your-attr') для обох атрибутів і вихід, якщо один з них все ще порожній, є першим рішенням, АЛЕ він не обробляє випадок, коли встановлений лише один атрибут, а інший вже має попереднє значення . Але Бог допомагає, це не питання насправді об’єктивне. Нелегко!
Володимир Бразиль

21

Можливо, ви зможете Object.assign(...)застосувати свої властивості до створеного елемента. Дивіться коментарі для отримання додаткової інформації.

Майте на увазі , що heightі widthатрибути певного в пікселях , а не відсотки. Вам доведеться використовувати 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 тощо, доступні лише для читання, тому це не вдається. Я подивився на дескриптори, і вони є доступниками лише із геттером (невизначений сеттер).
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це не буде працювати styleв IE або обробниках подій (ви все одно не повинні). Код вище обробляє style, але не події.

Документація


Для запису: IE7 ->'Element' is undefined
KooiInc

Так, справедливо. Забув про IE7 та їх COM-об'єкти. Ви можете перевантажити document.createElementта document.getElementByIdобробити це .... або просто обернути функціональність у функцію. Відредагована відповідь, щоб включити цю нотатку
Chris Baker

2
більш спрощена рекурсивна версія: jsfiddle включає в себе шину IE
Keleko

Мені дуже подобається спрощена версія Keleko! Єдине, у вашій версії у вашому JSFiddle немає внутрішнього тексту. Я спробував додати else if (за [prop] === html) {this.innerHTML = set [prop]; } і це не спрацювало. Я отримую повідомлення про помилку. Як я можу додати параметр innerText?
Джессіка

Ця відповідь дозволяє використовувати один об’єкт, який містить атрибути елементів, властивості css (потенційно у вкладеному об’єкті) та innerHTML. Він також показує, як використовувати цю модифікацію прототипу елемента (хммм) або використовувати його як звичайну функцію (ааааа). Хороша робота!
Ендрю Віллемс

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


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

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

@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", наприклад:

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, щоб викинути помилку, якщо заданий аргумент не є об'єктом.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.