Ad/iklan :







Search.Pencarian Menu

Add text send email to rh3252705.adda@blogger.com or Click this (Text porn Will delete) | Tambah teks kirim email ke rh3252705.adda@blogger.com atau Klik ini (Teks porno akan dihapus)
Total post.pos : 13631+

[Go Make Things] Combining light DOM and shadow DOM in a Web Component

For the last few weeks, I've been complaining about the shadow DOM. As much as I think it's an anti-pattern, there are some times where the shadow DOM can be situationally useful.

Today, I wanted to show you how you can mix-and-match the light DOM and the shadow DOM in a single Web Component.

Let's dig in!

Our Web Component

Let's imagine we have a <count-up> custom element…

<count-up></count-up>

When our Web Component JavaScript instantiates, it renders into a <button>, and a [role="status"] element that displays how many times the <button> has been clicked…

<count-up>  	<button>Count up!</button>  	<div role="status">Clicked 42 times</div>  </count-up>

With everything in the light DOM, we can easily style our elements from a global stylesheet.

If you have default button styles in your CSS, you don't even need to do anything special here. The Web Component will just pick up those global styles.

button {  	background-color: rebeccapurple;  	border: 0;  	border-radius: 0.25em;  	color: #fff;  	padding: 0.5em 1em;  }

So why would we want the shadow DOM at all?

Your code can get broken in unpredictable ways

Imagine for a moment that someone does something silly, like set [role="status"] elements to display: none

[role="status"] {  	display: none;  }

Now, our Web Component is basically useless.

Users can click it as many times as they want. The component will keep track of it, and update the text. But the user will never see it.

I'm not sure this is a real concern in most apps, but I could see it being the kind of thing that could happen with third-party embedded widgets.

Here, encapsulating just the stuff you don't want users to mess with in the shadow DOM might be a way to prevent that from happening.

The light DOM-only version

First, let's look at how the light-DOM only version of this Web Component works.

We define our count-up custom element, and pass in a class that extends the HTMLElement

customElements.define('count-up', class extends HTMLElement {  	// ...  });  

Inside the constructor(), we'll define a count attribute to keep track of how many times the button is clicked.

constructor () {    	// Always call super first in constructor  	super();    	// Set attributes  	this.count = 0;    }  

Next, we'll create a button element, assign it to a property, and give it some text. We'll also create a div, give a role of status, and give it some text.

Then, we'll .append() both of them inside the custom element.

constructor () {    	// Always call super first in constructor  	super();    	// Set attributes  	this.count = 0;    	// Create the button  	this.btn = document.createElement('button');  	this.btn.textContent = 'Count up!';    	// Create the announcement text  	this.announce = document.createElement('div');  	this.announce.setAttribute('role', 'status');  	this.announce.textContent = `Clicked ${this.count} times`;    	// Append HTML into the DOM  	this.append(this.btn);  	this.append(this.announce);    }  

Finally, we'll add a click event listener to the button, and use the handleEvent() method as our built-in event handler.

constructor () {    	// Always call super first in constructor  	super();    	// Set attributes  	this.count = 0;    	// ...    	// Event listener  	this.btn.addEventListener('click', this);    }  

Inside the handleEvent() method, we'll increase the count by 1, then update the displayed text.

handleEvent () {  	this.count++;  	this.announce.textContent = `Clicked ${this.count} times`;  }  

Here's a working demo.

Using the Shadow DOM for select elements

We can use the shadow DOM for just the [role="status"] element.

To do that, we'll first attachShadow() to create our shadow root

constructor () {    	// Always call super first in constructor  	super();    	// Set attributes  	this.count = 0;    	// Creates a shadow root  	this.root = this.attachShadow({mode: 'closed'});    	// ...    }  

When we go to .append() our announce element, we'll first add a <slot> to the shadow root.

Then, we'll append the announce element into the root instead.

With the <slot>, our <button> would not be displayed. With it, it shows up in the light DOM.

constructor () {    	// Always call super first in constructor  	super();    	// Set attributes  	this.count = 0;    	// Creates a shadow root  	this.root = this.attachShadow({mode: 'closed'});    	// ...    	// Append HTML into the DOM  	this.append(this.btn);  	this.root.innerHTML = `<slot></slot>`;  	this.root.append(this.announce);    	// Event listener  	this.btn.addEventListener('click', this);    }  

Here's another demo.

You'll notice that even with the [role="status"] element set to display: none, everything still works correctly.

Cheers,
Chris

Want to share this with others or read it later? View it in a browser.

Share :

Facebook Twitter Google+
0 Komentar untuk "[Go Make Things] Combining light DOM and shadow DOM in a Web Component"

Back To Top