2015-02-14 3 views
4

Я пытаюсь найти способ инкапсулировать Javascript без использования iframes. В идеале я бы хотел загрузить внешние компоненты HTML (виджеты) на родительскую страницу без двухэтапного процесса загрузки, который поставляется с использованием iframes (сначала загружается страница хоста, и только тогда загружается содержимое iframe).Shadow DOM: можно ли инкапсулировать JS?

Можно ли сделать это с помощью некоторых новых технологий веб-компонентов - тени DOM/шаблонов/импорта? Мне удалось приблизиться к добавлению HTML в теневой DOM и инкапсуляции CSS, но не смог подтвердить, можно ли получить отдельный документ для выполнения javascript компонента.

ответ

3

Веб-компоненты, используемые через HTML imports, инкапсулируют как Тень DOM HTML , так и Связанный скрипт.

Чтобы сузить терминологию, давайте рассмотрим, что у нас есть полимерный компонент core-ajax. Вот the code. Как вы могли видеть, он не предоставляет никакой разметки HTML вообще, инкапсулируя только сценарий.

После импорта на хост-сайта, как:

<link 
    rel="import" 
    href="https://www.polymer-project.org/components/core-ajax/core-ajax.html"> 

этот компонент обеспечивает возможность выполнения АЯКС вызовов без каких-либо Java-кодирования:

<core-ajax 
    auto 
    url="http://gdata.youtube.com/feeds/api/videos/" 
    params='{"alt":"json", "q":"chrome"}' 
    handleAs="json" 
    response='{{response}}' 
</core-ajax> 

выше будет загружать (так как auto атрибут установлен) содержимого указанного URL-адреса и поместить ответ в связанную переменную response. Другой способ общения с этим компонентом является обеспечение обработчика вместо привязки переменной шаблона для ответа:

- response='{{response}}' 
    + on-core-response="{{handleResponse}}" 

Можно реализовать handleResponse функцию в данной страницы яваскрипт и это все.

UPD Хотя в настоящее время нет возможности отличить основной документ и один используемый теневого DOM, эту функцию is being discussed в течение почти трех лет в w3c mailgroups. Дискуссия далека от заключения, хотя и в таких аспектах, как «не разрешаем ли мы их полностью в авторском пространстве».

+1

Thanks @mudasobwa! Имеется ли у сценария, который загружается через полимер, отдельный документ? Мне особенно интересно разделить контекст скриптов, аналогично запуску сценариев в разных кадрах. – Sasha

+0

Я бы предложил вам прочитать спецификацию W3C по импорту. Нет, «document» будет таким же (и нет возможности создавать другой встроенный документ, кроме 'iframe', и я уверен, что навсегда не будет такой возможности.) – mudasobwa

+0

Спасибо! [Этот ответ] (http://stackoverflow.com/questions/14338817/can-a-shadow-dom-secure-my-elements/14346490#14346490), по-видимому, подразумевает, что это будет поддерживаться через Shadow DOM в будущем, но мне любопытно, есть ли уже решение с другими методами. – Sasha

0

Это не связано с теневым dom, но оно связано с инкапсулированием компонентов полностью с помощью javascript: https://benfrain.com/sandbox-local-htmlcss-code-snippets-inside-iframe-style-guidespattern-libraries/

в основном вы создаете узел Iframe и впрыснуть CSS и JavaScript в него:

var newIframe = document.createElement('iframe') 
newIframe.contentWindow.document.open('text/html', 'replace') 
var content = '<!DOCTYPE html><html><head>'+CSS+'</head><body>'+HTML+JS+'</body></html>' 
newIframe.contentWindow.document.write(content) 
newIframe.contentWindow.document.close() 

Чтобы полностью изолировать JavaScript от доступа к ее родительской странице, я полагаю, вы можете изменить родительскую страница Профиля document.domain с каким-то произвольно сгенерированный домен, так что к новому ifr ame, родительская страница будет выглядеть как ее в другом домене и не имеет способа изменить свой домен для соответствия. Это будет связано со всеми обычными ограничениями безопасности. Затем вы можете спокойно поговорить с ребенком iframe через postmessage.

Теоретически вы также можете реализовать некоторую связь, чтобы автоматически изменять размер элемента iframe в зависимости от его содержимого, имитируя не-iframe-элемент в потоке.

Это то, о чем я хочу поэкспериментировать в будущем, но еще не опробовал.

0

Да, вы можете добавить <style> и <script> теги внутри шаблона (сниппет работает только в браузерах, поддерживающих Shadow DOM):

// Create the shadow DOM 
 
var shadow = document.querySelector('#testOutput').createShadowRoot(); 
 

 
// Get the template fragment and add it to the shadow DOM 
 
shadow.appendChild(document.querySelector('#testTemplate').content);
<template id="testTemplate"> 
 
    <script> 
 
    alert('Hello from the component'); 
 
    </script> 
 
</template> 
 

 
<div id="testOutput">shadow</div>

Или вы можете добавить их прямо в тени DOM.

Однако, это currently broken by content security policy and is a high XSS risk.

Смежные вопросы