Одновременная установка нескольких атрибутов для элемента с помощью 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%");
JP Silvashy
источник
1
Ответ от @Quantastical using Object.assign()стоит посмотреть тем, кто не хочет создавать вспомогательную функцию - работает для «всех перечислимых и собственных свойств».
benvc
4
Я пролистал все ответы, надеясь, что через 7 лет после публикации этого вопроса будет какое-то обновление ES7, благодаря чему нам не придется писать нашу собственную функцию, такую ​​как ответ
@Ariel

Ответы:

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установить прокладку ... или просто обернуть функциональность в функцию. Отредактированный ответ, включающий эту заметку
Крис Бейкер
2
более упрощенная рекурсивная версия: jsfiddle включает прокладку IE
Келеко
Мне очень нравится упрощенная версия Келеко! Единственное, что в вашей версии нет innerText в вашем JSFiddle. Я пробовал добавить еще if (at [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/

jfriend00
источник
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))
Компьютерщик Devigner
источник
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

KooiInc
источник
@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);
Доктор JavaB
источник
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, чтобы выдать ошибку, если данный аргумент не является объектом.

Суфьяне Хедиди
источник