影子根 getElementsByClassName [英] Shadow Root getElementsByClassName

查看:65
本文介绍了影子根 getElementsByClassName的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 LitElement 创建自定义 Web 组件.我对它相当陌生,并决定尝试制作图像幻灯片.我使用 W3Schools 幻灯片作为参考在修改它以用作 LitElement 时.问题是,当我尝试使用 document.getElementByClassName 时,我什么也没得到.我很熟悉这个问题,因为我正在使用 Shadow DOM,所以我将其更改为 this.shadowRoot.getElementsByClassName.不幸的是,我被告知我尝试使用的不是函数.当我使用 LitElement 和 shadow dom 时,如何按类名获取元素?如果你想看看我的组件是什么样子的,这里是代码:

import { LitElement, html} from '@polymer/lit-element';类 ImageGalleryElement 扩展了 LitElement {静态获取属性(){ 返回 {幻灯片索引:{类型:数字},}};构造函数(){极好的();this.slideIndex=1;this.showSlides(this.slideIndex);}//下一个/上一个控件plusSlides(n) {this.showSlides(this.slideIndex += n);}//缩略图图像控件当前幻灯片(n){this.showSlides(this.slideIndex = n);}showSlides(n) {变量 i;console.dir(this.shadowRoot);var slides = this.shadowRoot.getElementsByClassName("mySlides");控制台目录(幻灯片);var dots = this.shadowRoot.getElementsByClassName("dot");如果(n>slides.length){this.slideIndex = 1}if (n <1) {this.slideIndex = slides.length}for (i = 0; i 

<div class="mySlides 淡入淡出"><div class="numbertext">2/3</div><img src="../../img/img-nature-wide" style="width:100%"><div class="text">标题二</div>

<div class="mySlides 淡入淡出"><div class="numbertext">3/3</div><img src="../../img/img-mountains-wide" style="width:100%"><div class="text">标题三</div>

<!-- 下一个和上一个按钮 --><a class="prev" @click="${this.plusSlides(-1)}" >&#10094;</a><a class="next" @click="${this.plusSlides(1)}">&#10095;</a>

<br><!-- 点/圆圈--><div style="text-align:center"><span class="dot" @click="${this.currentSlide(1)}"></span><span class="dot" @click="${this.currentSlide(2)}"></span><span class="dot" @click="${this.currentSlide(3)}"></span>

`;}}//向浏览器注册元素customElements.define('image-gallery-element', ImageGalleryElement);

解决方案

getElementsByClassName() 方法仅适用于 HTML 文档或元素.

shadowRoot 是一个文档片段 通过继承,不是 Document 也不是 HTML 元素.

相反,您应该使用 querySelectorAll().

更新

这是相同的行为:

注意 1

getElementById() 在使用 document.createElement

创建的(内存中)节点上不可用

测试选择器方法:https://jsfiddle.net/CustomElementsExamples/bfge7mtj/

注意事项 2

请注意插槽内容未移动到 shadowDOM,它保留在 ligthDOM 中

当您将元素从 lightDOM(在主 DOM 中)移动到 shadowRoot 时,
Live Nodelist 将被清空

letpieces = document.getElementsByTagName("[此处为TAGNAME]");console.warn(tags);//列出所有标签this.shadowRoot.append(...this.children);console.warn(tags);//空

I am using LitElement to create custom Web Components. I am fairly new at it and decided to try making image slideshow. I used W3Schools slideshow as reference while modifying it to work as LitElement. The problem is, that when I am trying to use document.getElementByClassName I am not getting anything. I am familiar with this issue since I am working with Shadow DOM so I changed it to this.shadowRoot.getElementsByClassName. Unfortunately, I get told that what I am trying to use is not a function. How Do I get elements by class name when I am working with LitElement and shadow dom? In case you want to see how my component looks like, here is the code:

import { LitElement, html} from '@polymer/lit-element';

class ImageGalleryElement extends LitElement {

static get properties() { return {
    slideIndex: { type: Number },
  }};

constructor(){
    super();

    this.slideIndex=1;
    this.showSlides(this.slideIndex);
}

// Next/previous controls
plusSlides(n) {
    this.showSlides(this.slideIndex += n);
}

// Thumbnail image controls
currentSlide(n) {
    this.showSlides(this.slideIndex = n);
}

showSlides(n) {
    var i;
    console.dir(this.shadowRoot);
    var slides = this.shadowRoot.getElementsByClassName("mySlides");
    console.dir(slides);
    var dots = this.shadowRoot.getElementsByClassName("dot");
    if (n > slides.length) {this.slideIndex = 1} 
    if (n < 1) {this.slideIndex = slides.length}
    for (i = 0; i < slides.length; i++) {
        slides[i].style.display = "none"; 
    }
    for (i = 0; i < dots.length; i++) {
        dots[i].className = dots[i].className.replace(" active", "");
    }
    slides[this.slideIndex-1].style.display = "block"; 
    dots[this.slideIndex-1].className += " active";
}


render(){
return html`
    <style>
        * {box-sizing:border-box}

        /* Slideshow container */
        .slideshow-container {
            max-width: 1000px;
            position: relative;
            margin: auto;
        }

        /* Hide the images by default */
        .mySlides {
            display: none;
        }

        /* Next & previous buttons */
        .prev, .next {
            cursor: pointer;
            position: absolute;
            top: 50%;
            width: auto;
            margin-top: -22px;
            padding: 16px;
            color: white;
            font-weight: bold;
            font-size: 18px;
            transition: 0.6s ease;
            border-radius: 0 3px 3px 0;
            user-select: none;
        }

        /* Position the "next button" to the right */
        .next {
            right: 0;
            border-radius: 3px 0 0 3px;
        }

        /* On hover, add a black background color with a little bit see-through */
        .prev:hover, .next:hover {
            background-color: rgba(0,0,0,0.8);
        }

        /* Caption text */
        .text {
            color: #f2f2f2;
            font-size: 15px;
            padding: 8px 12px;
            position: absolute;
            bottom: 8px;
            width: 100%;
            text-align: center;
        }

        /* Number text (1/3 etc) */
        .numbertext {
            color: #f2f2f2;
            font-size: 12px;
            padding: 8px 12px;
            position: absolute;
            top: 0;
        }

        /* The dots/bullets/indicators */
        .dot {
            cursor: pointer;
            height: 15px;
            width: 15px;
            margin: 0 2px;
            background-color: #bbb;
            border-radius: 50%;
            display: inline-block;
            transition: background-color 0.6s ease;
        }

        .active, .dot:hover {
            background-color: #717171;
        }

        /* Fading animation */
        .fade {
            -webkit-animation-name: fade;
            -webkit-animation-duration: 1.5s;
            animation-name: fade;
            animation-duration: 1.5s;
        }

        @-webkit-keyframes fade {
            from {opacity: .4} 
            to {opacity: 1}
        }

        @keyframes fade {
            from {opacity: .4} 
            to {opacity: 1}
        }
    </style>
    <!-- Slideshow container -->
    <div class="slideshow-container">

        <!-- Full-width images with number and caption text -->
        <div class="mySlides fade">
            <div class="numbertext">1 / 3</div>
            <img src="../../img/img-snow-wide" style="width:100%">
            <div class="text">Caption Text</div>
        </div>

        <div class="mySlides fade">
            <div class="numbertext">2 / 3</div>
            <img src="../../img/img-nature-wide" style="width:100%">
            <div class="text">Caption Two</div>
        </div>

        <div class="mySlides fade">
            <div class="numbertext">3 / 3</div>
            <img src="../../img/img-mountains-wide" style="width:100%">
            <div class="text">Caption Three</div>
        </div>

        <!-- Next and previous buttons -->
        <a class="prev" @click="${this.plusSlides(-1)}" >&#10094;</a>
        <a class="next" @click="${this.plusSlides(1)}">&#10095;</a>
    </div>
    <br>

    <!-- The dots/circles -->
    <div style="text-align:center">
        <span class="dot" @click="${this.currentSlide(1)}"></span> 
        <span class="dot" @click="${this.currentSlide(2)}"></span> 
        <span class="dot" @click="${this.currentSlide(3)}"></span> 
    </div>
`;
}
} 
// Register the element with the browser
customElements.define('image-gallery-element', ImageGalleryElement);

解决方案

The getElementsByClassName() method works only on a HTML Document or element.

The shadowRoot is a Document Fragment by inheritance, not a Document nor a HTML element.

Instead you should use querySelectorAll().

Update

It's the same behavior for:

Note 1

getElementById() is not available on (in memory) nodes created with document.createElement

Test Selector Methods: https://jsfiddle.net/CustomElementsExamples/bfge7mtj/

Note 2

Be aware slotted content is not moved to shadowDOM, it remains in ligthDOM

When you move Elements from lightDOM (in main DOM) to shadowRoot,
the Live Nodelist will be emptied

let pieces = document.getElementsByTagName("[TAGNAME here]");
console.warn(tags);// lists all tags
this.shadowRoot.append(...this.children);
console.warn(tags);// empty

这篇关于影子根 getElementsByClassName的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆