e111077
It sometimes makes working with _slotted_ children in a non-lock-in way difficult in terms of state synchronization as opposed to props.children in React. The solution here in an app would be to use a state manager, but it's much more difficult for components that do not want to require the user to use a state manager e.g. design systems.
Additionally, hydration and customElements.define() upgrade order is a different consideration compared to other mono-state frameworks when it comes to SSR.
In terms of state management:
There are plenty of tools out there like lit-mobx shopped by Adobe. The team has also made some examples that show how easy it is to integrate your own state manager into Lit using ReactiveController such as Redux. There is also work being done such as example implementations of Preact Signals integration:
https://github.com/lit/rfcs/blob/preact-signals/rfcs/NNNN-pr...
import '/home/user/project/node_modules/lit/index.js'
A relative specifier: import '../node_modules/lit/index.js'
Or a URL Specifier: import 'https://unpkg.com/lit?module'
So you have four-ish options to tell the browser where to look for 'lit':1. Use a server that will use the node module resolution algorithm and transforms it to a relative specifier as it encounters the import (transform/build-ish?)
2. Use experimental "import maps" to go fully buildless to tell the browser where to point that bare module to (buildless)
3. Bundle all your code (build step)
4. Use a bundle from a CDN
Here are some examples of each:
Server that transforms import specifiers (lit.dev does this by default):
https://lit.dev/playground/#gist=9092862a77acf73dd1e6faa73a3... (build-ish)
Import Maps (2):
https://lit.dev/playground/#gist=0c4f66396b333c82cb27e7dd3b2... (buildless)
https://lit.dev/playground/#gist=91c0b286698612b013eb81881ff... (build-ish)
Url Specifiers (2):
https://lit.dev/playground/#gist=05655736300f0425644e61a6264... (buildless)
https://lit.dev/playground/#gist=6d23e8e8dadacd7488bdec81d0f... (build-ish)
hope this helps with some of your questions
Author also talks a lot about the issues with losing control of the component model when using preact
lit-html is completely different from web components and not meant to replace Polymer. lit-html is a library that just handles rendering and lit-element, which is meant to replace polymer uses lit-html as its renderer to make web coponents.
https://twitter.com/BenDelarre/status/1453038054503944194
TL;DR they're using everything that's on the standards track - just waiting for the others to implement them
https://developer.mozilla.org/en-US/docs/Web/API/HTMLUnknown...
* Custom Elements
* Shadow DOM (seems to be optional in practice)
* HTML Template Elements
* ES Modules (formerly HTML Imports)
1. Libraries like lit-html have syntax highlighting and tooling to do type checking.
For the developer: https://marketplace.visualstudio.com/items?itemName=runem.li...
For node: https://www.npmjs.com/package/lit-analyzer
For other Web Component libraries: https://www.npmjs.com/package/web-component-analyzer
2. Totally agree on slots. They suck and were hamstringed by Safari in spec talks. Libraries like LitElement have the concept of reflecting a property to an attribute and it's really easy to do so. Also, Chrome had a property explorer in dev tools that just got deprecated which also sucks.
3. Attributes are strings, yes, but you can also set properties on a component. Easy to have a setter and getter for a property (can easily be turned into a TS decorator) that just calls a render method on change, but again, the cost for attributeChangedCallback to serialize a primitive is very low. Passing objects should just be sent as a prop, but also, passing objects to child web components we've found is a bad habit. Often the props of an object should be spread (easy to make a directive of this in lit-html) over the props of the child and arrays typically easier to turn their contents into DOM nodes.
Also none of this takes into consideration of a web component using a state library like redux.
https://stackblitz.com/edit/lit-element-react-attributes-loc...
https://www.polymer-project.org/2.0/start/first-element/step...
The reason you have to define what an element 'is' is for backwards-compat reasons. Additionally, the properties definition block is there simply for attribute -> property serialization so that you can set properties declaratively in the HTML as attributes. The property declaration is also used for tooling schema enforcement just as you suggested it should really be there for. You do not need a properties block at all since Polymer uses webcomponents, and as you said, elements can handle arbitrary attributes (and attributes set in JS with the exception of the data- attributes [1]).
In Polymer 2, you simply set the function hook just like you wanted. Polymer 3 which is essentially just a refactoring of Polymer 2 introduces JS Modules. An example would be:
import {Polymer} from 'pathToPolymer';
export class IconToggle extends Polymer.Element {
static get is() { return 'icon-toggle' }
observedAttributes() { return ['toggleIcon'] }
attributeChangedCallback(name, old, new) { if(name === 'toggleIcon') {...} }
connectedCallback() { super.connectedCallback(); this.addEventListener('pressed', this.onPressed.bind(this)); }
onPressed(evt) { this.pressed = !this.pressed; }
}
customElements.define(IconToggle.is, IconToggle);
This example, does not use the properties but the native attributeChangedCallback [2], it does not explicitly define properties and it can still set this.pressed, and you can easily add a 'cats' attribute if you want which can then be accessed via this.getAttribute('cats') like any other native element. Polymer is written so that all the code is executable in the browser even with the JSX-like template syntax [3]. But with the move to JS modules, a webpack configuration can easily add extra functionality like not even having to define the event listeners or the observed attributes.[1] https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement...
[2] https://developer.mozilla.org/en-US/docs/Web/Web_Components/...
element.foo = 123;
vs element.setAttribute('foo', '123');> This gets progressively worse as your components grow in complexity. Imagine adding a span around the text in p?
In this case you simply type in the span inside the template tag similar to what you have in the React JSX and then just importNode the contents into your webcomponent.