DEV Community

Discussion on: Web components with vanilla JavaScript

Collapse
 
dannyengelman profile image
Danny Engelman • Edited

Since you explicitly asked for comments.

It is your component and content.
It is unlikely there are going to be Event Listeners added by "the outside"
That means you don't need addEventListener (can attach multiple listeners)

this._tooltipContainer.addEventListener(
  "mouseover",
  this._showTooltip.bind(this)
);
Enter fullscreen mode Exit fullscreen mode

can be replaced with an inline Event listener: (overwrites any previously declared listener)

this._tooltipContainer.onmouseover = (evt) => this._showTooltip(evt);
Enter fullscreen mode Exit fullscreen mode

And a function call instead of a function reference; so you don't need oldskool bind

Since these Event listeners are on DOM elements created by your component, it is also unlikely "the outside" is going to reference these DOM elements.
That means any attached Event Listeners will be removed by the GC (Garbage Collection) proces; and there is no need for removeEventListener.

You usualy only need removeEventListener for listeners you attached on DOM elements outside your component. (eg: document.addEventListener)


Also.. you want to write small re-usable components;

SInce you use powerful shadowDOM, there is only one <span>

Rewrite:

this._tooltipContainer = this.shadowRoot.querySelector(
      "#tooltip-container"
);
Enter fullscreen mode Exit fullscreen mode

Remove the id, and write:

this._tooltipContainer = this.shadowRoot.querySelector("span");
Enter fullscreen mode Exit fullscreen mode
Collapse
 
leeoc profile image
Lee O'Connell

Thanks for your comments, I will definitely be using inline event listeners in the future! Still quite new to JavaScript and have a long way to go

Collapse
 
dannyengelman profile image
Danny Engelman

One more thing that helps: inline Event listener is what you create in HTML:

<span onmouseover="functioncall"></span>

Thus span.onmouseover = (evt) => functioncall ...

overwrites (or sets!) the HTML declared Event

Collapse
 
dannyengelman profile image
Danny Engelman

I was too soon with my <span> remark; missed that you added a second span; can't you work that in you base HTML somehow?

Thread Thread
 
dannyengelman profile image
Danny Engelman • Edited

That double span didn't leave my mind today..

I would write it like this: jsfiddle.net/CustomElementsExample...

<my-tooltip tip-text="World!">Hello</my-tooltip>
<script>
  customElements.define("my-tooltip", class Tooltip extends HTMLElement {
    constructor() {
      super()
        .attachShadow({mode: "open"})
        .innerHTML = /*html*/ `
            <style>
             :host{ font-size: 24px; display: inline-block }
             span:not(:empty) {
                   padding: 1rem;
                   border-radius: 10px;
                   background-color: black;
                   color: white;
               }
            </style>
            <slot></slot> πŸ‘‰ <span></span>`;
      const tooltip = this.shadowRoot.querySelector("span");
      this.onmouseover = (evt) => {
        tooltip.innerHTML = this.getAttribute("tip-text") || "Default Text";
      }
      this.onmouseleave = (evt) => {
        tooltip.innerHTML = "";
      }
    }
  })
</script>
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
leeoc profile image
Lee O'Connell

Love this! Never thought a web component could be so clean. Haven’t seen the :not() css operator before, thanks for your comments, definitely have picked up a few new ideas and things to learn 😊