2016-03-04 19 views
8

Zdefiniowałem niestandardowy element i chcę wykonać skrypt tylko wtedy, gdy element niestandardowy zostanie uaktualniony do zarejestrowanego typu. Przypadek użycia polega na tym, że muszę wywołać niestandardową metodę.Sposób wykonywania skryptu po zaktualizowaniu elementu niestandardowego

Główny plik html wygląda następująco:

<project-list></project-list> 
<script> 
    var project_list = document.getElementsByTagName("project-list")[0] 
    project_list.custom_method("some_data"); 
</script> 

Element niestandardowy jest zarejestrowany w imporcie HTML tak:

<script> 
    "use strict"; 
    var currentScript = document._currentScript || document.currentScript; 

    class ProjectList extends HTMLElement { 

    createdCallback(){ 
     console.log("created"); 
    } 

    custom_method(data) { 
     console.log("custom_method() OK"); 
     console.log(data); 

     this.innerHTML = data; 
    } 

    } 

    document.registerElement("project-list", ProjectList); 
</script> 

Moje pytanie jest prosta: jak upewnić się, że skrypt w głównym pliku html jest wywoływana tylko po tym, jak element niestandardowy uzyskał swoją metodę custom_method?

Szukam eleganckiego rozwiązania. Coś, o czym pomyśleliby autorzy specyfikacji. Nie mam nic przeciwko zmianie architektury (na przykład przez przeniesienie javascript z głównego pliku na inny niestandardowy element, jeśli jest to konieczne).

+1

w przeglądarkach, które implementują specyfikację, tworzenie elementu i dołączanie go będzie synchronizowane. pod względem zakodowanych tagów jednak, afaik, nie istnieje zdarzenie "allComponentsReady" podobne do DOM. jednym ze sposobów jest podniesienie niestandardowego zdarzenia na "dokumencie" z komponentu i użycie tego zdarzenia, tak jak zdarzenie 'onload()' dla kodu strony wymagającego niestandardowych metod. możesz również zajrzeć do czegoś takiego jak redux, aby połączyć wiele odmiennych komponentów internetowych i metod aplikacji w sposób, który nie jest do dupy. – dandavis

+0

@dandavis: Oto, co robię. Ale ustawiłem też flagę. Jeśli flaga jest ustawiona, komponent jest już skonfigurowany, a metoda niestandardowa może zostać natychmiast wykonana. W przeciwnym razie jest zaplanowane na wypadek zdarzenia. Wysłałem odpowiedź z kodem, którego używam. – MarcG

+0

@dandavis: Aby podłączyć wiele odmiennych komponentów internetowych: jeśli jakiś składnik internetowy zależy od innych, to musi poczekać, aż WSZYSTKIE inne składniki będą gotowe, zanim ustawi/wywoła własne flagi/zdarzenia. – MarcG

Odpowiedz

3

Sync HTML importu

Jak sugeruje @dandavis, ze względu na sync domyślne zachowanie <link> i <script> elementów, po prostu trzeba umieścić swoje tagi w odpowiedniej kolejności: rejestracja przed wywołanie metody.

Albo zamiast tego można wywołać metodę niestandardową gdy DOMContentLoaded lub zdarzenie window.onload jest zwolniony, jak poniżej:

window.onload = function() 
 
{ 
 
    var project_list = document.getElementsByTagName("project-list")[0] 
 
    project_list.custom_method("some_data")  
 
}
<project-list></project-list> 
 

 
<script> 
 
    "use strict"; 
 
    var currentScript = document._currentScript || document.currentScript; 
 

 
    class ProjectList extends HTMLElement { 
 

 
    createdCallback(){ 
 
     console.log("created"); 
 
    } 
 

 
    custom_method(data) { 
 
     console.log("custom_method() OK"); 
 
     console.log(data); 
 

 
     this.innerHTML = data; 
 
    } 
 

 
    } 
 

 
    document.registerElement("project-list", ProjectList); 
 
</script>

ASYNC importu HTML

Jeżeli dla niektórych powody, dla których chcesz wczytać plik importu HTML asynchronicznie, możesz poczekać na wydarzenie link.onload. W tym momencie | <script> Wewnątrz importu zostało już wybrane, element niestandardowy zarejestrowany i utworzony.

<html> 
<head> 
    <title></title> 
    <meta charset="utf-8" /> 
    <link rel="import" href="projectList.html" id="projectList" async> 
    <script> 
    projectList.onload = function() 
    { 
     console.log("import {loaded}") 
     var project_list = document.getElementsByTagName("project-list")[0] 
     project_list.custom_method("some_data") 
    } 
    </script> 
</head> 
<body> 
    <project-list id="pl"></project-list> 
    <script> 
     console.warn("custom_method is " + pl.custom_method) //undefined 
    </script> 
</body> 
</html> 

Z WebComponents.js PolyFill

W tej sytuacji polyfill nie instancję utworzony obiekt bezpośrednio po import jest załadowany. Zamiast tego należy słuchać przypadku WebComponentsReady:

document.addEventListener("WebComponentsReady", function() 
{ 
    console.log("WebComponentsReady") 
    var project_list = document.getElementsByTagName("project-list")[0] 
    project_list.custom_method("some_data") 
}) 

Działa z Firefox, IE 11, a także z Chrome.

+0

To działałoby w Chrome, ale w Firefoksie z polyfillą Polymer, to nie zadziała. Jest zawsze asynchroniczny – user6020072

+0

Myślę, że jest to związane z tym błędem: https://github.com/webcomponents/webcomponentsjs/issues/431 – user6020072

+0

W przypadku rozwiązania wykorzystującego wiele przeglądarek zaktualizowałem swoją odpowiedź. – Supersharp

Powiązane problemy