Хорошо, люди, потерпите меня. Это будет длинный ответ. Он может стать немного волосатым. Прежде всего, это было решение Polymer 1.x. Я не знаю, что из этого изменилось для версии 2.0.
TL;DR: мы получаем URL-адреса .HTML и используем JavaScript для создания атрибута link
(импорт HTML) для загрузки элемента. Мы проверяем с помощью Polymer, используя Polymer.isInstance(element)
, чтобы увидеть, был ли установлен объект или нет.
Вот код:
Чтобы это работало, я использовал iron-pages
и пользовательский JavaScript.
У нас есть наше приложение, как показано ниже:
Примечание*: Следующий код у меня был в том же файле, вы можете разделить его по своему усмотрению.
<!-- Main Entry point for the application. This will work as the main "Controller"-->
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/app-route/app-location.html">
<link rel="import" href="../../bower_components/app-route/app-route.html">
<link rel="import" href="../../bower_components/iron-pages/iron-pages.html">
<dom-module id="pgarena-app">
<template>
<pgarena-action-config></pgarena-action-config>
<app-route route="{{route}}"
pattern="/:page"
data="{{data}}"
tail="{{tail}}">
</app-route>
<iron-pages selected="[[data.page]]" attr-for-selected="title" fallback-selection="404">
<pgarena-home-app title="" route="[[tail]]"></pgarena-home-app>
<pgarena-tournament-app title="tournaments" route="[[tail]]"></pgarena-tournament-app>
<!--<pgarena-clash-app title="clash" route="[[tail]]"></pgarena-clash-app>-->
<pgarena-account-app title="account" route="[[tail]]"><content></content></pgarena-account-app>
<pgarena-teams-app title="teams" route="[[tail]]"></pgarena-teams-app>
<div title="404">
<h1>{{data.page}} could not be found!</h1>
</div>
</iron-pages>
</template>
<script>
(function () {
'use strict';
Polymer({
is: 'pgarena-app',
ready: function () {
/* console.log("Route is ");
console.log(this.data.page);
console.log(this.tail);*/
document.addEventListener('iron-select',
function (event) {
/*
console.log("---------------------");
console.log(event);
console.log("---------------------");*/
var element = getSelectedElement(event);
var tagName = element.tagName.toLowerCase();
LazyLoad(Polymer, element, tagName, event.target);
});
}
});
})();
</script>
Сначала кое-что:
- Мое приложение называется: "pgarena-app"
- Я не знаю, было ли это исправлено, но у элемента app-route есть проблема с двусторонней привязкой данных. Это означает, что для железных страниц мне пришлось использовать двойные скобки
[[]]
для односторонней привязки данных.
- Маршрут приложения передает информацию из URL-адреса на железные страницы, чтобы он мог переключать различные элементы.
- Это не обязательно, и я не знаю, правильно ли это сделать. Я разделил свое приложение на «представления», которые сами по себе являются элементами. Они загружают все элементы, необходимые для этого «представления». Примечание. Это никакого эффекта при отложенной загрузке.
Обратите внимание, что элементы не включены в URL-адрес, потому что мы собираемся загружать их лениво.
Давайте перейдем к части JavaScript этого элемента:
<script>
(function () {
'use strict';
Polymer({
is: 'pgarena-app',
ready: function () {
document.addEventListener('iron-select',
function (event) {
var element = getSelectedElement(event);
var tagName = element.tagName.toLowerCase();
LazyLoad(Polymer, element, tagName, event.target);
});
}
});
})();
</script>
Код здесь простой. Мы определяем наш элемент и прослушиваем событие выбора железа. Это сигнализирует нам о том, что была выбрана страница железа. Мы лениво загружаем элемент, если его там нет. Магия, стоящая за этим, кроется в пользовательском LazyLoad
JavaScript, который приведен ниже.
<script>
/**
* Defines all the routes of the imports in here
*
* This is how it goes: The Key name is the tag name of the element.
* The value is the relative URL from the elements folder.
*
* You then get the element's tag name and look for it.
*
* DO NOT PUT TRAILING SLASH BEFORE THE URL! Thanks :)
**/
var PGArena = PGArena || {};
PGArena.LazyLoad =
{
"pgarena-home-app": "routes/home/pgarena-home-app.html",
"pgarena-tournament-app": "routes/tournament/pgarena-tournament-app.html",
"pgarena-account-app": "routes/account/pgarena-account-app.html",
"pgarena-clash-app": "routes/clash/pgarena-clash-app.html",
"pgarena-teams-app": "routes/teams/pgarena-teams-app.html",
"pgarena-tournament-index-view": "views/tournament/pgarena-tournament-index-view/pgarena-tournament-index-view.html",
"pgarena-tournament-list-view": "views/tournament/pgarena-tournament-list-view/pgarena-tournament-list-view.html",
"pgarena-account-index-view": "views/account/pgarena-account-index-view/pgarena-account-index-view.html",
"pgarena-account-login-view": "views/account/pgarena-account-login-view/pgarena-account-login-view.html",
"pgarena-account-register-view": "views/account/pgarena-account-register-view/pgarena-account-register-view.html",
"pgarena-account-confirm-email-view": "views/account/pgarena-account-confirm-email-view/pgarena-account-confirm-email-view.html",
"pgarena-account-oauth-view": "views/account/pgarena-account-oauth-view/pgarena-account-oauth-view.html",
"pgarena-clash-index-view": "views/clash/pgarena-clash-index-view/pgarena-clash-index-view.html",
"pgarena-clash-brawl-view": "views/clash/pgarena-clash-brawl-view/pgarena-clash-brawl-view.html",
"pgarena-teams-index-view": "views/team/pgarena-teams-index-view/pgarena-teams-index-view.html",
"pgarena-teams-create-view": "views/team/pgarena-teams-create-view/pgarena-teams-create-view.html"
};
/**
* This variable keeps track of all the vulcanized elements.
*
**/
PGArena.Vulcanized = {
}
/**
* Global Placeholder for checking which is the selected item of the iron-selectors that
are ready for lazy loading.
**/
PGArena.IronSelected = {
}
/**
* LazyLoad
*
* Lazy Loads the elements as needed. This function is triggered by iron-select
* event. If the element is already registered, then it is not loaded again.
*
* Polymer => Dependency Injection of the Polymer object. (Polymer itself)
* element => The element (DOM-wise: a.k.a tags with everything)
* elementName => The element's name.
* selectorTrigger => The element who triggered the select.
**/
function LazyLoad(Polymer, element, elementName, selectorTrigger) {
if (Polymer.isInstance(element)) {
// console.log(elementName + " is already registered ;)");
return;
} else {
//console.log(elementName+" isn't registered. On its way for Lazy Loading!");
}
//console.log("Lazy Load Started");
var hasProp = PGArena.LazyLoad.hasOwnProperty(elementName);
if (!hasProp) {
console.log("Property " + elementName + " not found for Lazy Loading");
return;
}
var href = PGArena.LazyLoad[elementName];
LoadImportAsync(href, elementName, selectorTrigger);
}
function Spinner(elementName, active) {
var paperId = 'js-' + elementName;
var queryName = active ? elementName : paperId;
var createElem = active ? 'paper-spinner-lite' : elementName;
var elem = document.querySelector(queryName);
var spinner = document.createElement(createElem);
spinner.setAttribute('active', '');
if (elem === null || elem === undefined)
return;
console.log("Element Name is");
console.log(queryName);
console.log("Element is");
console.log(elem);
console.log("Spinner is:");
console.log(spinner);
if (active) {
spinner.setAttribute('id', 'js-' + elementName);
console.log("replacing time");
elem.parentNode.replaceChild(document.createTextNode("Caca"), elem);
//elem.parentNode.replaceChild(spinner, elem);
}
else {
console.log("Replaced");
//elem.parentNode.replaceChild(elem, spinner);
}
}
function ForcedLoad() {
}
/**
* Loads the required import and appends it to the document. It really doesn't
* matter where it is appended.
*
**/
function LoadImportAsync(href, elementName) {
var link = document.createElement('link');
link.rel = 'import';
link.href = getBaseUrl() + "/NodeJS/Polymer/app/elements/" + href;
link.setAttribute('async', ''); // make it async!
link.onload = function () { Spinner(elementName, false); }
link.onerror = function (e) { console.log("There was an error loading " + elementName + ". Please Check the URL") };
document.head.appendChild(link);
}
function getBaseUrl() {
var pathArray = location.href.split('/');
var protocol = pathArray[0];
var host = pathArray[2];
return protocol + '//' + host;
}
/**
* On non-blink browsers (a.k.a Firefox , Edge, Internet Explorer)
* The event.srcElement is undefined. We need to search for it ourselves.
*
* The way we do that is that we get the current targetted element which is the iron form.
* Retrieve its selection mechanism and the supposed element's index.
*
* We proceed by query Selecting the element in the DOM all the way until we nab it.
* Then we are faced with the next challenge. We don't know if the element is using an
* index-based approach (0, 1, 2...) or an attribute approach(title="home", title="tournament",etc.)
*
* So we proceed to fetch its selection mechanism by grabbing the attrForSelected. If null, it means that
* it is using the index-based approach. We continue and get the children position at the element.
*
* Note that selectedAttr variable will return me either the index or the selected attribute's value.
* So it's going to be 0, 1, 2 if using the index based approach.
*
**/
function getSelectedElement(event) {
if (event.srcElement !== undefined)
return event.srcElement.selectedItem;
var element = event.target;
//Get the current selected attribute:
var selectedAttr = element.selected;
//Gets the attribute that is being used for selection:
var attrForSelected = element.attrForSelected;
//This means that it is not using index based
if (attrForSelected !== null) {
return element.querySelector('[' + attrForSelected + '="' + selectedAttr + '"]');
}
//Continues using index based:
var childelem = element.children[parseInt(selectedAttr)];
return childelem;
}
</script>
Первое, что мы делаем, это определяем URL-адреса относительно документа, который у меня есть. Я делаю это, определяя json с ключом, имя которого является атрибутом title
для iron-pages
и значением с относительным URL-адресом этого документа (приложение pgarena).
Я имею в виду, что в случае, если я хочу загрузить pgarena-tournament-app
, а моя pgarena-app
(моя основная точка входа в приложение) находится в www/polymer/pgarena-app.html
, а мое приложение pgarena-tournament-app находится в www/polymer/routes/tournament/pgarena-tournament-app.html
, поскольку это относительно, мой JSON будет:
var PGArena = PGArena || {}; PGArena.LazyLoad = { "турнир" : "маршруты/турнир/pgarena-tournament-app.html", };
Примечание PGArena.LazyLoad может быть чем угодно, это глобальная переменная, которую я определил в пространстве имен PGArena.
Затем мы видим, что вызывается код LazyLoad:
function LazyLoad(Polymer, element, elementName, selectorTrigger) {
if (Polymer.isInstance(element)) {
// console.log(elementName + " is already registered ;)");
return;
} else {
//console.log(elementName+" isn't registered. On its way for Lazy Loading!");
}
//console.log("Lazy Load Started");
var hasProp = PGArena.LazyLoad.hasOwnProperty(elementName);
if (!hasProp) {
console.log("Property " + elementName + " not found for Lazy Loading");
return;
}
var href = PGArena.LazyLoad[elementName];
LoadImportAsync(href, elementName, selectorTrigger);
}
Что я делаю здесь, так это проверяю, есть ли ссылка на элемент, который я хочу отложить, в JSON, который я определил (PGarena.LazyLoad). Если его там нет, то я регистрирую это сообщение. Если он есть и не загружен, я загружаю его асинхронно, создавая импорт HTML и добавляя его в заголовок:
/**
* Loads the required import and appends it to the document. It really doesn't
* matter where it is appended.
*
**/
function LoadImportAsync(href, elementName) {
var link = document.createElement('link');
link.rel = 'import';
link.href = getBaseUrl() + "/NodeJS/Polymer/app/elements/" + href;
link.setAttribute('async', ''); // make it async!
link.onload = function () { Spinner(elementName, false); }
link.onerror = function (e) { console.log("There was an error loading " + elementName + ". Please Check the URL") };
document.head.appendChild(link);
}
Пожалуйста, обратите внимание (я не знаю, исправили ли они это). Существует полифилл для импорта HTML для Firefox, Edge и Safari (я полагаю). Полифилл использует XHR (AJAX) для загрузки импорта!!! Я упоминаю об этом, потому что в начале я пытался перехватить импорт HTML, и в Google Chrome это не сработало.
Позвольте мне знать, если вам нужно что-нибудь еще. Как видите, я пытался использовать счетчик, но у меня не получилось. Надеюсь это поможет!
person
Jose A
schedule
13.06.2017