【问题标题】:Shadow DOM in web components with Vue3使用 Vue3 的 Web 组件中的 Shadow DOM
【发布时间】:2021-08-26 11:20:00
【问题描述】:

我目前正在使用 Vue3 测试 Web 组件,并且想知道这个 Shadow DOM 是如何工作的。一些第三方库正在使用getElementById() 访问元素并抛出错误,因为该元素是null。 显然这是因为 Web 组件无法访问实际的 DOM。这意味着函数甚至无法找到组件本身中使用的 HTML 元素。谁能解释为什么会这样?那么我将如何访问这些元素?也许是shadowRoot

Test.vue:

<template>
<div id="test">Hello World!</div>
</template>

<script lang="js">
import {
    ref,
    onMounted
} from "vue";

export default {
    setup(props) {
        onMounted(() => {
            // NULL
            console.log(document.getElementById("test"));
        });
    }
}
</script>

main.js:

import { defineCustomElement } from 'vue'
import Test from './Test.vue'

const ExampleElement = defineCustomElement(Test)

// register
window.customElements.define('test-component', ExampleElement)

【问题讨论】:

  • 它在我的电脑上正确运行,得到了#test 元素
  • 应该可以,我在 codesandbox 中测试过
  • 显示 main.js 文件
  • @Radeanu 我再次对此进行了测试。该元素仍然为空。你知道获取元素的方法吗?也许用 shadowRoot?

标签: javascript vue.js web-component vuejs3


【解决方案1】:

是的,shadowDOM 是用来封装内容的。

如果您不想要这种行为,请不要使用 shadowDOM
但是,如果您使用的是工具,它可能会对您强制执行 shadowDOM,
在这种情况下,放弃该工具并使用 Vanilla JavaScript 创建一个组件,这不是火箭科学。

如果您正在学习 Web 组件,最好先学习技术,而不是工具……因为有工具的傻瓜仍然是傻瓜。

如果自定义元素(带有 shadowDOM)存在于 DOM 中,并且注册到 mode:"open",您可以通过以下方式查询其内容:

document.querySelector("test-component").shadowRoot.querySelector("#test")

如果你想在页面中找到所有 Web Components,你可以这样做一些事情像这样:

// findElements takes a function definition, the output must be Truthy or Falsy
function findElements( accept = x => customElements.get(x.localName) || 0) {
  function log() {
    console.log(`%c findElements `, `background:purple;color:yellow`, ...arguments);
  }
  let node, elements = [], shadowRootCount = 0;
  function diveNode( diveRoot ) {
    // IE9 was last to implement the TreeWalker/NodeIterator API ... in 2011
    let iterator = document.createNodeIterator(
      diveRoot,
      NodeFilter.SHOW_ELEMENT,
      node => accept(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT
    );
    while ( node = iterator.nextNode() ) {
      if (node.shadowRoot) {
        log(`dive into shadowRoot #${++shadowRootCount} at`, node.outerHTML);
        [...node.shadowRoot.children].forEach( diveNode );
      }
      elements.push(node);
    }
  }
  diveNode( document.body ); // initial dive location
  log(elements.length, `elements found`,[elements]);
  //return elements;
}
findElements((x) => true); // find all DOM elements
findElements(); // find all Custom Elements

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-05
    • 2020-03-03
    • 1970-01-01
    • 2014-07-19
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多