DEV Community

Cover image for Learn basic Web Components

Learn basic Web Components

Lenvin Gonsalves on April 20, 2021

Even though web components have been losing steam in recent days, they have a lot of advantages. One of them is writing framework-agnostic componen...
Collapse
 
dannyengelman profile image
Danny Engelman • Edited

One thing nearly everyone does is due to incorrect documentation:

constructor() {
    super();
    this.attachShadow({ mode: "open" });
    this.shadowRoot.appendChild(template.content.cloneNode(true));
  }
Enter fullscreen mode Exit fullscreen mode

can be written as:

constructor() {
    super() // sets and returns 'this'
      .attachShadow({ mode: "open" })  //sets and return this.shadowRoot
      .append(template.content.cloneNode(true));
  }
Enter fullscreen mode Exit fullscreen mode

Note the use of append and appendChild. In most examples appendChilds return value is never used. append can added multiple text-nodes or elements.

And the global template.innerHTML isn't necessary either:

constructor() {
    super()
      .attachShadow({ mode: "open" })
      .innerHTML = ` ... any HTML here... `;
  }
Enter fullscreen mode Exit fullscreen mode

Docs also say you "use super() first in constructor"

That is incorrect also.

You can use any JavaScript before super(); you just can not use this until it is created by the super() call

Collapse
 
98lenvi profile image
Lenvin Gonsalves

Thanks for letting us know about this. The code looks much cleaner, and yes! not creating a template element would be much better as the global namespace wouldn't be polluted. I'll add this comment to the article ๐Ÿ˜€

Collapse
 
bennypowers profile image
Benny Powers ๐Ÿ‡ฎ๐Ÿ‡ฑ๐Ÿ‡จ๐Ÿ‡ฆ

Shouldn't be innerHTMLing in constructor. Better to use the template

Collapse
 
dannyengelman profile image
Danny Engelman • Edited

If you don't take my word; then maybe you take this guy his comment on innerHTML

I don't know the guy personally .. but Justin Fagnani sounds familiar ๐Ÿ˜›

Collapse
 
dannyengelman profile image
Danny Engelman

Can you motivate that statement, Benny

innerHTML and append(Child) all do the same: they add content to a DOM

That .createElement"template") takes extra CPU cycles; content is parsed once.
With .innerHTML= content is also parsed once.

So there is only benefit if code does template.cloneNode(true) multiple times

Thread Thread
 
bennypowers profile image
Benny Powers ๐Ÿ‡ฎ๐Ÿ‡ฑ๐Ÿ‡จ๐Ÿ‡ฆ

if you know you're only going to use the element once, yeah there's no difference.

But if you're going to construct the element several times, then you're going to invoke the parser on each instance.

If the element's shadow DOM is extensive, that could add up fast.

Moreover, keeping the template static means it's parsed up front.

Collapse
 
webpreneur profile image
Zsolt Gulyas

Truly said. Altough I wouldn't say just because of this, that the docs are "incorrect". Maybe the first one is more readable for newcomers. Anyway, super useful comment though. Thanks.

Collapse
 
dannyengelman profile image
Danny Engelman • Edited

See what code newcomers have to dig through (unless they don't RTFM) in the attachShadow MDN documentation: developer.mozilla.org/en-US/docs/W...

If you understand "// Always call super first in constructor" is incorrect
you can write that 33 lines constructor (most likely) without any comments:

constructor() {

  let span = document.createElement('span');

  function countWords() {
    let node = this.parentNode;
    let text = node.innerText || node.textContent;
    let count = text.trim().split(/\s+/g).length;
    span.innerText = 'Words: ' + count;
  }

  super()
   .attachShadow({mode: 'open'})
   .append( span );

  countWords();
  setInterval(()=> countWords() , 200);
}
Enter fullscreen mode Exit fullscreen mode

If you want to score W3C points; feel free to update that MDN article.

I did some MDN updates; then concluded there is way more effect adding comments to Web Component blogposts.
And I recently published my first Dev.to post explaining Web Components are about semantic HTML (IMHO)

And ... there is more wrong in that MDN Count Words example..

  • this.parentNode DOM access should be done in the connectedCallback, as the DOM might not even exist when the constructor runs

  • <p is="word-count"></p> Will never work in Safari, because Apple only implemented Autonomous Elements and (for the past 5 years) has strong arguments to not implement Customized Built-In Elements

Collapse
 
darkwiiplayer profile image
๐’ŽWii ๐Ÿณ๏ธโ€โšง๏ธ

These APIs are all very low-level and using them directly isn't all that practical. I usually prefer creating some simple wrappers around them, small and simple enough that I can just copy-paste them into any random project without having to worry about updating them.

For the HTMLElement class I've created this "improved" version that takes care of as much of the typical preamble without sacrificing too much flexibility or building a whole new framework.

Collapse
 
dannyengelman profile image
Danny Engelman • Edited

Low-Level ??

They are part of the JavaScript engine, no lower than an Array or any other API

A low-level programming language is a programming language that provides little or no abstraction from a computer's instruction set architectureโ€”commands or functions in the language map that are structurally similar to processor's instructions. Generally, this refers to either machine code or assembly language.

You can "improve" your code:

content.forEach( element => this.appendChild(element) );
Enter fullscreen mode Exit fullscreen mode

to

this.append(...content);
Enter fullscreen mode Exit fullscreen mode

MDN append documentation

Collapse
 
webpreneur profile image
Zsolt Gulyas

You should add webcomponents tag to your article too.

Collapse
 
98lenvi profile image
Lenvin Gonsalves

Thanks! will be adding it right away.

Collapse
 
caleb15 profile image
Caleb Collins-Parks

web components are losing steam? :O

Collapse
 
dannyengelman profile image
Danny Engelman • Edited

Yes, they do.

They don't run on coal like Frameworks, they are part of JavaScripts' core technologies, thus run on modern power. No steam required any longer.