如何从影子中获取元素-DOM

How to get element from shadow-DOM

我在访问 shadow-root 时遇到问题。我需要获取 img 但它不起作用。这是我的页面:

<link rel="import" href="/frontend/src/ui/breadcrumb.html">
<dom-module id="bread-crumb">
    <template>
        <style include="breadcrumb"></style>
        <div id="wrapper">
            <template is="dom-if" if="{{pageInfo.title}}">
                <div class="left">
                    <img id="img" src$="{{pageInfo.icon}}">
                    <span>{{pageInfo.title}} <strong>{{pageInfo.part}}</strong></span>
                </div>
            </template>
            <div class="links">
                <template is="dom-repeat" items="[[links]]">
                    <a class$="{{_getSelected(item.selected)}}" href$="{{item.link}}"> {{item.title}} </a>
                </template>
                <!-- <template is="dom-if" if="{{item.title}}">
                    <a href$=""
                </template> -->
            </div>
        </div>
    </template>
    <script>
    class BreadCrumb extends Polymer.Element {
        static get is() {
            return 'bread-crumb'
        }
        _getSelected(selected){
            return selected ? "selected" : "";
        }

        connectedCallback() {
            this._imageHide();
        }

        _imageHide() {
            let image = this.$.img;
            if(image.src == null || image.src == undefined)
                image.classList.add("hidden");
        }
    }

    customElements.define(BreadCrumb.is, BreadCrumb);
    </script>
</dom-module>

我也试过这个 let image = this.shadowRoot.querySelector('#img'); 但它也不起作用。以上抛出错误:

Cannot read property 'img' of undefined

我尝试了其他方式 let image = this.shadowRoot.querySelector('#img'); 这给了我:

Cannot read property 'querySelector' of null

我做错了什么?有什么建议吗?

关于您的元素的第一个问题是您的 connectedCallback 没有 "forward" 对 super 的调用。那应该是你方法中的第一件事,所以它会变成:

  connectedCallback() {
    super.connectedCallback();
    this._imageHide();
  }

我猜您只是从代码中跳过了一部分,pageInfo.title 实际上是一个真值。但由于我不知道 when/how 这些值已设置,我猜测另一个问题可能是 _imageHide 方法从 connectedCallback 运行并且标签可能为时过早实际被标记到页面中。

除非在设置这些值时存在一些复杂性,否则我猜您只需将调用延迟到尽可能短的时间,但将其包装在没有第二个参数的 setTimeout 中就可以了。所以实际上 connectedCallback 会是:

  connectedCallback() {
    super.connectedCallback();
    setTimeout(() => {
      this._imageHide();
    });
  }

现在第三个问题是 this.$ "shortcut" 不适用于有条件地添加到页面中的元素。所以你应该像你说的那样使用 querySelector,或者 getElementById,比如:

let image = this.shadowRoot.getElementById('img');