Веб-компонент с внутренними js и css не показывает контент - PullRequest
1 голос
/ 07 октября 2019

Изучая веб-компоненты, я попытался создать такие нетривиальные, как этот, оборачивая скользкую карту Leaflet. Но я не могу заставить его работать ... Вот моя попытка - как вы видите, карты нет:

enter image description here

website-with-webcomponent-online.html

<html>
<head>
  <title>A Leaflet map!</title>
  <script src="./leaflet-map-webcomponent-online.js"></script>
</head>
<body>

  Text before Leaflet.
  <leaflet-map></leaflet-map>
  Text after Leaflet.

</body>
</html>

leaflet-map-webcomponent-online.js

(function(){
const template = document.createElement('template');
template.innerHTML = `
<style>
    display: block;    
    .map-root{
        border: 1px solid black;
        height: 180px;
    }
</style>
<h1>Leaflet web component</h1>
<div id="map" class="map-root"></div>
`;

class CustomLeafletMapWebComponent extends HTMLElement {
    constructor() {
        super(); 
        console.log('CustomLeafletMapWebComponent constructed!');
        this._shadowRoot = this.attachShadow({ 'mode': 'open' });
        this._shadowRoot.appendChild(template.content.cloneNode(true));
        this.loadDependencies();
    }

    connectedCallback() {
        console.log('CustomLeafletMapWebComponent connected!');

        const mapRoot = this._shadowRoot.querySelector(".map-root")

        // timeout to avoid error "L is not defined"
        setTimeout(function(){

            // initialize the map
            var map = L.map(mapRoot).setView([42.35, -71.08], 13);

            // load a tile layer
            L.tileLayer('http://tiles.mapc.org/basemap/{z}/{x}/{y}.png',
              {
                attribution: 'Tiles by <a href="http://mapc.org">MAPC</a>, Data by <a href="http://mass.gov/mgis">MassGIS</a>',
                maxZoom: 17,
                minZoom: 9
              }).addTo(map);
        }, 100);
    }

    disconnectedCallback() {
        console.log('CustomLeafletMapWebComponent disconnected!');
    }

    attributeChangedCallback(name, oldVal, newVal) {
        console.log(`Attribute: ${name} changed!`);
    }

    adoptedCallback() {
        console.log('CustomLeafletMapWebComponent adopted!');
    }

    loadCssFile(cssfile){
        var link = document.createElement("link");
        link.rel = "stylesheet";
        link.href = cssfile
        this._shadowRoot.appendChild(link)
        // // Variation:
        // var head = document.getElementsByTagName("head")[0]
        // head.appendChild(link)
    }
    loadScriptFile(scriptfile){
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = scriptfile
        this._shadowRoot.appendChild(script)
        // // Variation:
        // var head = document.getElementsByTagName("head")[0]
        // head.appendChild(script)
    }
    loadDependencies(){
      this.loadCssFile("https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.css")
      this.loadScriptFile("https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.js")
    }
}
window.customElements.define('leaflet-map', CustomLeafletMapWebComponent);
})()

В небольшом варианте, в котором я добавляю скрипт и файл css в заголовок документа вместо теневого, это выглядит так: enter image description here

1 Ответ

2 голосов
/ 07 октября 2019

Нашел решение. Измените CSS шаблона на:

template.innerHTML = `
<style>
        .map-root{
            border: 1px solid black;
            height: 180px;
        }
</style>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.css">
<h1>Leaflet web component</h1>
<div id="map" class="map-root"></div>
`;

Не имеет значения, включаете ли вы leaflet.js в shadowdom или документ - по крайней мере, для этого примера.

loadScriptFile(scriptfile){
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = scriptfile
    var head = document.getElementsByTagName("head")[0]
    this._shadowRoot.appendChild(script)
}
loadDependencies(){
  //this.loadCssFile("https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.css")
  this.loadScriptFile("https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.js")
}
...