2017-05-07 15 views
5

Tôi đã một yếu tố xác định tùy chỉnh như sau:Không thể xây dựng lỗi 'CustomElement' khi tập tin JavaScript được đặt trong đầu

class SquareLetter extends HTMLElement { 
    constructor() { 
     super(); 
     this.className = getRandomColor(); 
    } 
} 
customElements.define("square-letter", SquareLetter); 

Khi tệp JavaScript được bao gồm trong HTML <head> thẻ, giao diện điều khiển báo cáo Chrome lỗi này :

Uncaught DOMException: Failed to construct 'CustomElement': The result must not have attributes

Nhưng khi tệp JavaScript được đưa vào trước thẻ kết thúc </body>, mọi thứ đều hoạt động tốt. Lý do là gì?

<head> 
    <script src="js/SquareLetter.js"></script> <!-- here --> 
</head> 
<body> 
    <square-letter>A</square-letter> 
    <script src="js/SquareLetter.js"></script> <!-- or here --> 
</body> 
+3

Bản sao có thể có của [Không thể truy cập các thuộc tính của phần tử tùy chỉnh từ hàm tạo của nó] (http://stackoverflow.com/questions/42251094/cannot-access-attributes-of-a-custom-element-from-its-constructor) – Supersharp

Trả lời

6

Lỗi này là chính xác, và có thể xảy ra trong cả hai trường hợp. Bạn nhận được may mắn vì một số hiện tại của Custom Elements không thực thi yêu cầu này.

Hàm tạo cho phần tử tùy chỉnh không được phép đọc hoặc ghi DOM của nó. Nó không nên tạo các phần tử con hoặc sửa đổi các thuộc tính. Công việc đó cần được thực hiện sau, thường trong phương thức connectedCallback() (mặc dù lưu ý rằng connectedCallback() có thể được gọi nhiều lần nếu phần tử bị xóa và được thêm lại vào DOM, vì vậy bạn có thể cần phải kiểm tra điều này hoặc hoàn tác thay đổi trong disconnectedCallback()).

Trích dẫn đặc tả WHATWG HTML, nhấn mạnh tôi:

§ 4.13.2 Requirements for custom element constructors :

When authoring custom element constructors, authors are bound by the following conformance requirements:

  • A parameter-less call to super() must be the first statement in the constructor body, to establish the correct prototype chain and this value before any further code is run.

  • A return statement must not appear anywhere inside the constructor body, unless it is a simple early-return (return or return this).

  • The constructor must not use the document.write() or document.open() methods.

  • The element's attributes and children must not be inspected, as in the non-upgrade case none will be present, and relying on upgrades makes the element less usable.

  • The element must not gain any attributes or children, as this violates the expectations of consumers who use the createElement or createElementNS methods.

  • In general, work should be deferred to connectedCallback as much as possible—especially work involving fetching resources or rendering. However, note that connectedCallback can be called more than once, so any initialization work that is truly one-time will need a guard to prevent it from running twice.

  • In general, the constructor should be used to set up initial state and default values, and to set up event listeners and possibly a shadow root.

Several of these requirements are checked during element creation, either directly or indirectly, and failing to follow them will result in a custom element that cannot be instantiated by the parser or DOM APIs. This is true even if the work is done inside a constructor-initiated microtask, as a microtask checkpoint can occur immediately after construction.

Khi bạn di chuyển tập lệnh để sau khi các yếu tố trong DOM, bạn gây ra các yếu tố hiện có để đi qua các "nâng cấp" bộ quá trình. Khi kịch bản trước phần tử, phần tử trải qua quá trình xây dựng tiêu chuẩn. Sự khác biệt này dường như gây ra lỗi không xuất hiện trong mọi trường hợp, nhưng đó là chi tiết triển khai và có thể thay đổi.

-1

Yếu tố đã không được nạp chưa nên không thể thay đổi, khi tải tập lệnh bên dưới phần tử có nghĩa là nó có thể thay đổi

Các vấn đề liên quan