Đặt nhiều thuộc tính cho một phần tử cùng một lúc bằng JavaScript


88

Làm cách nào để đặt nhiều thuộc tính cùng một lúc với JavaScript? Rất tiếc, tôi không thể sử dụng một khuôn khổ như jQuery trong dự án này. Đây là những gì tôi có bây giờ:

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

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

1
Câu trả lời từ @Quantastical bằng cách sử dụng Object.assign()đáng xem xét cho những người không muốn tạo hàm trợ giúp - hoạt động cho "tất cả các thuộc tính có thể liệt kêriêng ".
benvc

4
Tôi cuộn qua tất cả các câu trả lời, hy vọng rằng trong 7 năm kể từ khi câu hỏi này được đăng, sẽ có một số loại cập nhật ES7, giúp chúng tôi không phải viết hàm của riêng mình như câu trả lời của @ Ariel
krummens

Câu trả lời:


120

Bạn có thể tạo một hàm trợ giúp:

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

Gọi nó như thế này:

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

1
nó cũng không xảy ra cùng một lúc, vì vậy sẽ không ảnh hưởng đến hiệu suất.
vsync

Đây không phải là những gì anh ấy yêu cầu. Chúng ta cần phải biết làm thế nào để cải thiện hiệu suất
jbartolome

19
@jbartolome - Từ "hiệu suất" không được đề cập một lần trong câu hỏi. Tôi không biết bạn lấy khái niệm đó từ đâu. Câu hỏi dường như đang tìm cách để không phải gọi thủ công elem.setAttribute()nhiều lần.
jfriend00

Tôi không chắc câu hỏi thực sự muốn gì. Một kết quả tốt nhất có thể mong muốn là gọi thuộc tínhChangedCallback "chỉ một lần". Nếu tôi cần gọi một hàm phụ thuộc vào hai thuộc tính, thường thì thuộc tính attributeChangedCallback được gọi hai lần, mỗi lần thay đổi thuộc tính. Truy cập this.getAttribute ('your-attr') cho cả hai thuộc tính và thoát nếu một trong số chúng vẫn trống là giải pháp đầu tiên NHƯNG nó không xử lý trường hợp chỉ một thuộc tính được đặt và một thuộc tính khác đã có giá trị trước đó . Nhưng chúa giúp đây không phải là câu hỏi thực sự khách quan. Không dễ!
Vladimir Brasil

21

Bạn có thể sử dụng Object.assign(...)để áp dụng các thuộc tính của mình cho phần tử đã tạo. Xem bình luận để biết thêm chi tiết.

Hãy nhớ rằng heightwidthcác thuộc tính được xác định bằng pixel , không phải phần trăm. Bạn sẽ phải sử dụng CSS để làm cho nó trở nên linh hoạt.

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
Các thuộc tính, elem.height, v.v., ở chế độ chỉ đọc, vì vậy điều này không thành công. Tôi đã xem xét các bộ mô tả, và chúng là những bộ truy cập chỉ có getter (bộ định vị không xác định).
lukeuser

@lukeuser Cảm ơn bạn đã nhận xét. Tôi không biết rằng các thuộc tính đó là chỉ đọc.
người dùng

2
Đối với câu hỏi của bạn về "bạn không thể chỉ ..." Tôi hỏi điều này có lẽ khi bạn thực sự không thể chỉ.
JP Silvashy

2
@JPSilvashy Tôi không có ý định coi "bạn không thể" của mình là coi thường hoặc thể hiện dấu hiệu của sự vượt trội. Xin lỗi nếu nó đã làm. Tôi thực sự không chắc liệu đây có phải là câu trả lời phù hợp hay không vì tôi không phải là ninja JavaScript, vì vậy tôi hy vọng những người khác như lukeuser có thể kêu gọi để giúp củng cố logic.
người dùng

13

Nếu bạn muốn có cú pháp framework-esq ( Lưu ý: chỉ hỗ trợ IE 8+), bạn có thể mở rộng Elementnguyên mẫu và thêm setAttributeschức năng của riêng mình :

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

Điều này cho phép bạn sử dụng cú pháp như sau:

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

Hãy thử nó: http://jsfiddle.net/ywrXX/1/

Nếu bạn không thích mở rộng đối tượng máy chủ ( một số bị phản đối ) hoặc cần hỗ trợ IE7-, chỉ cần sử dụng nó như một hàm

Lưu ý rằng điều đó setAttributesẽ không hoạt động với styleIE hoặc trình xử lý sự kiện (dù sao thì bạn cũng không nên làm như vậy). Đoạn mã trên xử lý style, nhưng không xử lý các sự kiện.

Tài liệu


Đối với bản ghi: IE7 ->'Element' is undefined
KooiInc

Vâng, đủ công bằng. Quên về IE7 và các đối tượng COM của chúng. Bạn có thể quá tải document.createElementdocument.getElementByIdđể lấp cái này .... hoặc chỉ gói chức năng trong một chức năng. Câu trả lời đã chỉnh sửa để bao gồm ghi chú đó
Chris Baker

2
hơn đơn giản hóa phiên bản đệ quy: jsfiddle bao gồm một shim IE
Keleko

Tôi thực sự thích Keleko phiên bản đơn giản hóa! Điều duy nhất là, trong phiên bản của bạn, không có innerText trong JSFiddle của bạn. Tôi đã thử thêm else if (at [prop] === html) {this.innerHTML = set [prop]; } và nó không hoạt động. Tôi nhận được một lỗi. Làm cách nào để thêm cài đặt innerText?
Jessica

Câu trả lời này cho phép bạn sử dụng một đối tượng có chứa các thuộc tính phần tử, thuộc tính css (có thể nằm trong một đối tượng lồng nhau) và innerHTML. Nó cũng chỉ ra cách sử dụng điều này để sửa đổi nguyên mẫu phần tử (hmmm) hoặc sử dụng nó như một hàm bình thường (ahhh). Công việc tốt!
Andrew Willems

12

Bạn có thể tạo một hàm nhận một số đối số thay đổi:

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

Hoặc, bạn chuyển các cặp thuộc tính / giá trị vào một đối tượng:

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

Bạn cũng có thể tạo phương thức / trình bao bọc đối tượng có thể điều khiển của riêng mình:

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

Ví dụ làm việc: http://jsfiddle.net/jfriend00/qncEz/


11

Bạn có thể viết mã một hàm trợ giúp ES5.1:

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

Gọi nó như thế này:

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

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

4

Hoặc tạo một hàm tạo một phần tử bao gồm các thuộc tính từ các tham số

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%'sẽ không hoạt động khi sử dụng các thuộc tính. Để có chiều cao / chiều rộng là 100%, bạn cần các yếu tốstyle.height/style.width


@vsync Mặc dù tôi đánh giá cao sự phản đối ngẫu nhiên và xúc phạm của bạn, nhưng có rất ít sự khác biệt cơ bản giữa câu trả lời này và bất kỳ câu trả lời nào khác ở đây. Bình tĩnh.
Chris Baker

@Chris - đúng là ngẫu nhiên, vì tôi muốn quảng cáo câu trả lời này, vì vậy tôi phải từ chối câu trả lời ở trên nó. và vâng, nếu bạn có 1000 mục và bạn phải thay đổi 5 thuộc tính cho mỗi thuộc tính, tốt nhất bạn nên tạo lại chúng với các thuộc tính mới hơn là truy cập DOM 5000 lần, bạn có đồng ý không?
vsync

@vsync nếu bạn đang sử dụng chức năng sao chép / dán ngẫu nhiên mà bạn tìm thấy trên StackOverflow mà không xem xét hiệu suất đặc biệt liên quan đến kế thừa cho trường hợp sử dụng của bạn, thì bạn có thể gặp phải vấn đề lớn hơn. Hơn nữa, trong câu trả lời bạn đã phản đối, DOM sẽ không được truy cập 5000 lần, không nhiều hơn câu trả lời này - trong cả hai trường hợp, phần tử được đề cập chưa được chèn vào cây DOM. Câu trả lời này và câu trả lời của tôi làm tương tự, chúng tôi chỉ lặp lại các thuộc tính khác nhau.
Chris Baker

@Chris - Câu hỏi này không liên quan đến tôi. tại sao bạn lại nói về tôi và những gì tôi làm hay không? nó không liên quan. Câu trả lời của bạn không tốt lắm nếu một người cần thay đổi các thuộc tính của nhiều nút trên chính DOM, trong khi câu trả lời này tốt hơn một chút vì nó thúc đẩy một cách suy nghĩ tốt, nơi bạn tạo lại nút với tất cả các thuộc tính của nó và cài đặt nó trong DOM. Đây cũng không phải là lý tưởng hơn, bởi vì sử dụng clonephương pháp này sẽ được ưu tiên hơn. Không cần tạo toàn bộ nút từ đầu. Dù sao, ưu tiên hàng đầu là giảm thiểu quyền truy cập vào DOM, trường hợp sử dụng phổ biến nhất.
vsync

@vsync Từ "bạn" được sử dụng theo nghĩa trừu tượng, không có nghĩa là bạn với tư cách là một cá nhân (mà tôi khá chắc chắn bạn, vsynch, biết) mà cho người tiêu dùng giả định trong tương lai của những câu trả lời này. Một lần nữa, hai câu trả lời giống hệt nhau về chức năng. Bạn có thể tự do bỏ phiếu theo cách bạn muốn, ngay cả khi lập luận của bạn có sai sót (kiểm tra điểm chuẩn), nhưng hãy giữ cho bản thân những nhận xét trịch thượng.
Chris Baker

3

Thử đi

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: TẠI ĐÂY


1

sử dụng chức năng này để tạo và đặt các thuộc tính cùng một lúc

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

sử dụng nó như vậy

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

1

Tôi đoán đó là cách tốt nhất để đặt các thuộc tính cùng một lúc cho bất kỳ phần tử nào trong lớp này.

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

bạn có thể chỉ cần thêm một phương thức (setAttributes, với "s" ở cuối) vào nguyên mẫu "Phần tử" như:

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

bạn có thể xác định nó trong một dòng:

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

và bạn có thể gọi nó bình thường như khi bạn gọi các phương thức khác. Các thuộc tính được cung cấp dưới dạng một đối tượng:

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

bạn có thể thêm câu lệnh if để thông báo lỗi nếu đối số đã cho không phải là một đối tượng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.