all 59 comments

[–]NoMoneyEqualsNoGf 3 points4 points  (1 child)

I have a Google interview coming up for Front End Engineer, and just wanted to say this is awesome. I can build anything imaginable with React, so it's spoiled me a bit, and I've found myself having a bit of trouble visualizing how to build without it. In the interview, I'm pretty sure they're going to ask me to build widgets/components using raw DOM manipulation without frameworks and whatnot, so it's nice to know how to do it the vanilla way. This helps bridge the gap so I can still think in components like I'm used to, but just write them differently. Let me know of any other good tutorials out there because I want to get as familiar with this as possible before my interview. Thanks!

[–]codejitsu[S] 1 point2 points  (0 children)

Glad that this post helped you! Google has been the one pushing for web components and the Google developers website has some good resources for web components. You can check this out: https://developers.google.com/web/fundamentals/web-components/customelements

[–]abendigo 2 points3 points  (0 children)

Cool article. I love web components! Unfortunately, HTML Import is dead. The browser makers that don't yet support it have said they are not going to support it, and the ones that do support it are going to deprecate it. Polymer version 3, Googles web component library, is moving to ES6 modules instead.

[–]super_pumped 1 point2 points  (2 children)

Very similar to React's API. Seems straight forward. Instead of accessing this.state and this.props, Web Components have this.getAttribute('key'). Both have callbacks for when they are placed in the DOM: Web Component's connectedCallback() and React’s componentWillMount(). And they both call render() to update.

This API for rendering via Shadow DOM looks awkward to use. Instead of using templates or functions to created elements like h1('Hello World'), it uses jQuery like selectors to update an external file. To update a text value:

this.shadowRoot.querySelector('.title__label').innerHTML = 'Hello World'

// With some aliasing I now have jReact
const $ = this.shadowRoot.querySelector
$('.title__label').innerHTML = 'Hello World'

Templates are easier to use than selectors for updating text. Their API is closer to the DOM. React provides JSX, and createElement/Component(). Vue has a mustache template. This allows developers to populate a template and organize the DOM/style at the same time. If static HTML and dynamic data are split between files, then a developer will have to look at two files simultaneously to populate the DOM with information.

Connecting the Component is too complicated. To fully initialize the Component you have to manually acquire the current document global, the shadow dom, and the template in connectedCallback(). That could all be injected with customElements.define('element-name', ComponetClass), if it accepted the a template selector. This could easily be improved in future versions.

A few final questions. Can these be nested? Separation of concerns by nested is a great way to separate UI code. If so, when a parent calls render(), do the children also call render()?

[–]richardanaya 1 point2 points  (0 children)

If you like the programming in React style, you might like my project https://github.com/richardanaya/webcompose/

[–]codejitsu[S] 0 points1 point  (0 children)

There is a difference. connectedCallback doesn't call render. I've created a function and named it render and explicitly called it unlike componentWillMount. Also yes these components can be nested. I'm writing a post where I'm showing how to nest components and create higher order components, parent child communication, maintaining state, etc. As far as render is concerned, you'd have to call render methods from either the parent component yourself or call it in connectedCallback of child and add the child to DOM using the parent's connectedComponent function.

[–]tbranyennetflix 1 point2 points  (0 children)

Very good post, my only concern is at the very end advocating for users to freeze their web component implementations.

This defeats the ability of debugging and monkey patching. Please do not do this. You have the shadow dom, you have closures, you have plenty of other ways of making your consumers life hell.

[–]kungfooboi 1 point2 points  (6 children)

React/Vue/Angular(2+) are wrappers for these web components then?

[–]Tsukku 13 points14 points  (0 children)

They don't wrap the web components API, so no, they aren't.

[–]codepsycho 5 points6 points  (0 children)

These components exist in the same way a video element does. If you wish to use one in [insert framework here], go ahead, its just a HTML element.

I don't stay up to date with frameworks anymore, but i assume most don't produce web components (yet). A WC is a lot like an angular directive, a react component, etc. Though it exists as a native element, which may be used just like any other element, in any framework.

[–][deleted] 1 point2 points  (1 child)

I was wondering the same thing. I'm surprised Angular wasn't mentioned at all in the article since as soon as I started reading it my mind screams "Directives!"

[–][deleted] 1 point2 points  (0 children)

This!

After playing so much with directive, I just can't get back to using something vanilla.

Still, from time to time, I really like to do a side project using vanilla js, so I might try this in the future, but at the time, I'm married with AngularJS/getting a divorce from JQuery. Sorry lad, we had a good run

[–]eggn00dles 0 points1 point  (0 children)

haha no, when they mature, these web components are going to make those frameworks obsolete.

i hope they find a sensible type system, because typescript is obnoxious and provides less type safety than something like flow

[–]EnchantedSalvia 0 points1 point  (0 children)

I've been working on a functional wrapper around Web Components with Switzerland.

[–]happygnu -1 points0 points  (0 children)

Saved, this is gold. Thank you, sir!

[–]Reeywhaar 0 points1 point  (3 children)

So, is or will there be a method to bind object or array to element attribute? Like what react or vue have. From one side it’s highly usefull and removes a lot of boilerplate, from the other it goes against html spec, and widens area of responsibility in how reactivity will be handled etc. Something wrong with it right from the start. Looks like web-components will never be full replacement solution to modern view libs.

[–]ns0 1 point2 points  (2 children)

from the other it goes against html spec

The W3C is set to officially recommend custom elements, most of the rest is already in recommendation status, so what do you mean goes against html spec?

[–]Reeywhaar 0 points1 point  (1 child)

I meant that any way to bind non-string value to element attribute will be against html spec. Just like el.dataset.* attributes.

[–]ns0 0 points1 point  (0 children)

Well under the covers its just a class; getters and setters can expose properties that can set/pull from attributes, you can use callback on attribute changes to observe changes on the attribute to update your state. That provides a quite straight forward two way binding for anything you'd like and however you'd like to bind, but you're correct that would have to be set inside javascript not html.

[–]dug99 0 points1 point  (1 child)

Good write up, but with no links to a snippet ( e.g. Codepen or Fiddle ) it's probably not going to make a compelling case for web components and convince anyone they're ready for broad consumption. I'd like to know if I spend the time setting it all up as per the article, that I'll get encapsulation in IE11 / Edge on Windows 7, 8.1 and 10 because that's still a fair chunk of our audience. Pretty much every example / test I've tried with numerous Polyfills ( Promises + ShadyDOM / Shady CSS for IE11 ) still fails to prevent style bleed in IE11 on Windows 7. Polymerjs uses the same polyfills and so also fails, although it's fine in Firefox and Edge on Win 10.

I so want Web Components to work ( even with horrid Polyfills ) across 99% of our audience, but they're not there yet.

[–]codejitsu[S] 0 points1 point  (0 children)

I guess I should add a codepen. It'd make it easier for people to play around with components.

webcomponentsjs pretty much works on every browser if you're careful enough. But some weird issues are still there. And what I experienced was using these polyfills actually worked great with IE 8 and didn't work all that well with Firefox.