如何使用 shadow dom 创建聚合物自定义元素,以便可以访问它的 shadowRoot?

Posted

技术标签:

【中文标题】如何使用 shadow dom 创建聚合物自定义元素,以便可以访问它的 shadowRoot?【英文标题】:How can I create polymer custom element with shadow dom so that I can access it's shadowRoot? 【发布时间】:2017-02-10 08:55:50 【问题描述】:

我使用 Polymer-cli(0.16.0 版)搭建了一个聚合物项目,但无法使用控制台访问 shadow-root:

var element = document.getElementsByTagName("my-app")[0].shadowRoot 返回 undefined 所以看起来影子 DOM 处于关闭模式。

如何强制自定义元素使用打开模式,以便从外部访问它的 shadowRoot?

编辑 2: 这里的主要问题是访问 shadowRoot 需要做什么,所以我稍微改变了问题,使其与 shadow DOM 模式无关

编辑:

参考https://developers.google.com/web/fundamentals/getting-started/primers/shadowdom#advanced高级主题部分的关闭模式

重现场景的步骤:

npm install -g polymer-cli
mkdir my-app
cd my-app
polymer init starter-kit
polymer serve --open

一些代码sn-ps:

index.html:

...
<head>
...
    <script>
      // Setup Polymer options
      window.Polymer = 
        dom: 'shadow',
        lazyRegister: true
      ;

      // Load webcomponentsjs polyfill if browser does not support native Web Components
      (function() 
        'use strict';

        var onload = function() 
          // For native Imports, manually fire WebComponentsReady so user code
          // can use the same code path for native and polyfill'd imports.
          if (!window.HTMLImports) 
            document.dispatchEvent(
              new CustomEvent('WebComponentsReady', bubbles: true)
            );
          
        ;

        var webComponentsSupported = (
          'registerElement' in document
          && 'import' in document.createElement('link')
          && 'content' in document.createElement('template')
        );

        if (!webComponentsSupported) 
          var script = document.createElement('script');
          script.async = true;
          script.src = '/bower_components/webcomponentsjs/webcomponents-lite.min.js';
          script.onload = onload;
          document.head.appendChild(script);
         else 
          onload();
        
      )();

      // Load pre-caching Service Worker
      if ('serviceWorker' in navigator) 
        window.addEventListener('load', function() 
          navigator.serviceWorker.register('/service-worker.js');
        );
      
    </script>

    <link rel="import" href="/src/my-app.html">
...
</head>
<body>
    <my-app></my-app>
</body>
</html>

我的应用程序.html:

...
<dom-module id="my-app">

<template>
...
</template>

  <script>

    Polymer(

      is: 'my-app',

      properties: 

        page: 
          type: String,
          reflectToAttribute: true,
          observer: '_pageChanged'
        

      ,

      observers: [
      '_routePageChanged(routeData.page)'
      ],

      _routePageChanged: function(page) 
        this.page = page || 'view1';
      ,

      _pageChanged: function(page) 
        // Load page import on demand. Show 404 page if fails
        var resolvedPageUrl = this.resolveUrl('my-' + page + '.html');
        this.importHref(resolvedPageUrl, null, this._showPage404, true);
      ,

      _showPage404: function() 
        this.page = 'view404';
      

    );

  </script>

</dom-module>

【问题讨论】:

你能添加一些代码 什么是开合模式? 还要注意,如果你想在 Firefox 上 polyfill Shadow DOM,你应该下载 webcomponents.js 而不是不包含 Shadow DOM polyfill 的 webcomponents-lite.js。 控制台写了什么? 【参考方案1】:

如果您使用 shady DOM(默认),则没有 shadowRoot

请参阅https://www.polymer-project.org/1.0/docs/devguide/settings 如何启用影子 DOM。

这样的东西应该可以工作

var element = Polymer.dom(document.getElementsByTagName("my-app")[0]).root

更多详情见https://www.polymer-project.org/1.0/docs/devguide/local-dom

【讨论】:

已编辑以包含 dom 设置:它被定义为“影子”。 var element = Polymer.dom(document.getElementsByTagName("my-app")[0]).root 也从控制台返回 undefined 启用shadow DOM时,不需要Polymer.dom(...)document.getElementsByTagName("my-app")[0] 返回什么? document.getElementsByTagName("my-app")[0] 使用 .root 或 .shadowRoot 或 Polymer.dom 返回 &lt;my-app page="view1"&gt;#shadow-root (open)&lt;/my-app&gt;,它返回 undefined Google Chrome linux 版本 53.0.2785.116(64 位)Mozilla Firefox linux 49.0.1 抱歉,不知道。我只在 Dart 中使用 Polymer,不知道在 JS 中使用它的细节。【参考方案2】:

实际上它应该可以工作。请参阅下面的 sn-p。

也许您没有在正确的位置添加 dom: 'shadow' 设置。应该在&lt;link&gt;polymer.html之前定义。

output.textContent = document.querySelector('my-app').shadowRoot
<head>
  <script>
    window.Polymer = 
      dom: 'shadow',
      lazyRegister: true
    
  </script>
  <link rel=import href="https://rawgit.com/polymer/polymer/master/polymer.html">
</head>

<body>
  <dom-module id="my-app">
    <template>
      Hello
    </template>
    <script>
      Polymer(
        is: 'my-app'
      )
    </script>
  </dom-module>
  <my-app></my-app>
  <div id=output></div>
</body>

【讨论】:

我没有编辑代码,它是在问题的重现场景的步骤部分中搭建的。并且测试是在浏览器控制台上运行的,我也认为它应该运行但不 如果你认为问题不是你的错,你应该在编辑的网站上打开一个问题

以上是关于如何使用 shadow dom 创建聚合物自定义元素,以便可以访问它的 shadowRoot?的主要内容,如果未能解决你的问题,请参考以下文章

使用custom elements和Shadow DOM自定义标签

如何让导入的css字体/图标对shadow dom中的元素产生影响?

聚合:将样式应用于Shadow DOM下的元素

video视频标签自定义显示隐藏播放控件&Shadow DOM

Spark 2.0.0:如何使用自定义编码类型聚合 DataSet?

聚合物、影子 dom、事件和冒泡