2017-05-07 20 views
5

Mam element niestandardowy zdefiniowane tak:udało się skonstruować błąd „CustomElement” kiedy plik JavaScript jest umieszczony w głowicy

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

Gdy plik JavaScript jest włączone HTML <head> tagiem raporty konsoli Chrome ten błąd :

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

Ale gdy plik JavaScript jest włączone przed </body> kończącego tagu, wszystko działa bez zarzutu. Jaki jest powód?

<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

Prawdopodobny duplikat [Nie można uzyskać dostępu do atrybutów niestandardowego elementu od jego konstruktora] (http://stackoverflow.com/questions/42251094/cannot-access-attributes-of-a-ustom-element-from--constructor) – Supersharp

Odpowiedz

6

Błąd jest prawidłowy i może występować w obu przypadkach. Masz szczęście, ponieważ niektóre obecne implementacje elementów niestandardowych nie wymuszają tego wymogu.

Konstruktor dla niestandardowego elementu nie powinien czytać ani zapisywać swojego DOM. Nie powinno tworzyć elementów potomnych ani modyfikować atrybutów. Ta praca musi być wykonana później, zwykle w metodzie connectedCallback() (chociaż pamiętaj, że connectedCallback() można wywołać wiele razy, jeśli element zostanie usunięty i ponownie dodany do DOM, więc może być konieczne sprawdzenie tego lub cofnięcie zmian w disconnectedCallback()).

Cytując specyfikację WHATWG HTML nacisk Mine:

§ 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.

Podczas przesuwania skrypt po elementu w DOM, można spowodować istniejące elementy, aby przejść przez proces „upgrade”. Kiedy skrypt znajduje się przed elementem, element przechodzi przez standardowy proces konstrukcyjny. Ta różnica najwyraźniej powoduje, że błąd nie pojawia się we wszystkich przypadkach, ale jest to szczegół implementacji i może ulec zmianie.

-1

Element nie został jeszcze załadowany, więc nie może być zmieniony, ładuje skrypt poniżej elementu oznacza, że ​​może być zmieniona