Exploring the power of Vue3 with Shadow DOM in web components

I've been experimenting with web components using Vue3 and I'm curious about how the Shadow DOM works. I encountered an issue where a third party library was trying to access elements using getElementById() and it was throwing an error because the element was null. It seems that this is due to the restricted access from the web component to the actual DOM, making it difficult for functions to locate HTML elements used within the component itself. Can someone shed light on why this limitation exists? And how can I properly access these elements? Would using shadowRoot help?

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)

Answer №1

A fundamental aspect of shadowDOM is to encapsulate content within it

If you prefer not to have this behavior, then simply refrain from using shadowDOM.
However, some tools may impose the use of shadowDOM on you.
If that's the case, consider abandoning the tool and crafting a Component with Vanilla JavaScript instead, as it's not overly complicated.

For those delving into Web Components, it's advisable to grasp the underlying Technology before relying on a Tool... because even with a Tool in hand, one can still make foolish decisions.

In cases where the Custom Element (with shadowDOM) is present in the DOM and registered with mode:"open", you can access its contents using:

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

To locate all Web Components on a page, a possible approach could be:

// findElements requires a function definition that outputs Truthy or Falsy values
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 ) {
    // The TreeWalker/NodeIterator API reaching IE9 implementation only 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 diving point
  log(elements.length, `elements found`,[elements]);
  //return elements;
}
findElements((x) => true); // locating all DOM elements
findElements(); // identifying all Custom Elements

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Experiencing challenges during the creation of a NUXT build

Trying to build a Nuxt SSR app, but encountering an error related to the css-loader during the build command execution. The issue seems to be with Invalid options object. ERROR in ./node_modules/vue2-google-maps/dist/components/streetViewPanorama.vue (./no ...

Unable to locate module with React and Material-UI integration

When attempting to implement a Material button in my React app, I encountered the following error: Failed to compile. ./node_modules/@material-ui/core/styles/index.js Module not found: Can't resolve '/Users/hugovillalobos/Documents/Code/Lumiere ...

JQuery method for extracting a specific span's content from a div

I am faced with extracting specific text from a span within a div element. Below is the code snippet for my Div: '<div class="dvDynamic_' + pid + '"><p hidden="true">'+pid+'</p><span class="count_' + pid ...

Activate event in jQuery when clicking on a blank area, away from any div element

I need help figuring out how to hide a div when empty space on the margins of the page is clicked, as opposed to just any area outside of the div. I've managed to achieve this functionality when certain other divs are clicked, but I'm stuck on im ...

The anchor tag causes the tooltip to display outside of the td element

One of my requirements is to display the click percentage for each link in an HTML template that is dynamically fetched from a database. I attempted to show the click percentage for each anchor link by adding them to the `data-title` attribute using jQuery ...

Utilizing a variable string name for a method in Typescript Vue

My objective is to trigger a different function based on the value of a variable. However, when working in VS Code, I receive an error message that states: 'method' implicitly has a type of 'any' because 'type1Func' and &apos ...

Discovering the geometric boundaries of a body of text

Seeking help with determining the geometric bounds of text inside hyperlinks in an InDesign document. I've tried to do this using ExtendScript but haven't had any luck. // Loop through and export hyperlinks in the document for (k = 0; k < myD ...

Saving the author of a message from one function and transferring it to another

I'm currently working on a Discord bot that manages tickets as applications. I've almost completed it, but I want the bot to log the closed ticket when the -close command is used. I've experimented with different approaches, such as using a ...

Setting header details for optimal data transfer

Currently, there is a Java code snippet that I am working on which attempts to access the header information sent by an HTML page. Unfortunately, I do not currently have the specific HTML page in question. However, I still need to be able to access and m ...

What is the proper way to implement an if-else statement within objects?

Is there a way to convert the code below into an object structure so I can access nodID and xID keys from different files? The issue lies in the if statement within the code. My idea is to use export const testConfig = {} and import testConfig into any fil ...

How to Develop a Custom getText() Function for a Selenium Element?

Creating a custom Selenium getText() method that can retrieve either the node text or the node plus child text of an element is my current challenge. The default behavior of Selenium appears to utilize the Xpath .//string() method which includes the text o ...

How can I change an array to a string in JavaScript/jQuery and add a specific

Currently, I am tasked with the challenge of converting an array into objects. Furthermore, I also need to add something before each object is displayed. var arrayList = ["image1.jpg","image2.jpg","image3.jpg"]; The desired outcome should look like this ...

Refreshing dynamically added rows through ajax updates

I'm struggling to clearly articulate my problem. Currently, I have a function that retrieves values from a database using ajax and then dynamically adds each result as a row in a table. This allows users to edit or delete any row as needed. I'm ...

AngularJS - "Refrain from replicating items in a repeater"

I am facing an issue with creating HTML textarea elements for each member of an array. Despite consulting the AngularJS documentation and attempting different track by expressions, I am unable to render them. The problem arises when a user inputs the same ...

When the page is scrolled to 50 pixels, a modal pop-up will appear

I attempted to use cookies to store a value when the user clicks on a popup to close it, ensuring that the popup does not show again once closed. However, I am encountering an issue where the popup continues to open whenever I scroll, even after closing it ...

Securing Your Content - Preventing Users from Right-Clicking and Using F12 on Your Website

I am looking to disable the Right-Click function on my website or display an error message saying "Protected Content!" when someone tries to right-click. I want to prevent others from viewing my Source Code. Although I know how to disable Right-Click, I am ...

Controlling MVC controls dynamically using jQuery

I'm currently working on a table that contains multiple editable fields corresponding to an MVC model object. Each row has a cell with two buttons that toggle between edit and save functions when clicked. I've successfully implemented a mechanism ...

Instructions for launching an Android app from a website

Is it possible to invoke my app from HTML? For instance, I am able to successfully call a webpage from my app using this code. android code: startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse( "myDomain.com"))); ...

The AJAX response doesn't seem to be halting

My AJAX request looks like this: $.ajax({ url: "AutoRFQ_Vendors_ST.aspx/BindVesselGrid", type: "POST", timeout: 3000, data: JSON.stringify(sendingdata), ...

What could be causing the span class data to not be retrieved by the getText method

Looking to retrieve the value of a span class called 'spacer-right big project-card-measure-secondary-info' <span class="spacer-right big project-card-measure-secondary-info">1</span> snippet of code: browser.waitForEl ...