lit-html rerender weird phenomenon

Created on 25 Oct 2018  路  7Comments  路  Source: Polymer/lit-html

https://codepen.io/mantou132/pen/YJdQxb?editors=1000

When using method 1, custom-element will rerender;

but using method 2, custom-element no rerender;

screen shot 2018-10-25 at 23 03 21
screen shot 2018-10-25 at 23 03 41

Most helpful comment

This is a feature of JavaScript tagged template string literals.

When you tag a template string with a function, that function is called with an array of the static string components of the template, and arguments that represent the dynamic values of the template. Each time the tag function is invoked for the same template literal, the string array will be the same object. Lit-html uses this identity to uniquely identify different templates.

const tag = (strings, ...values) => { return {strings, values}};
const template = (value) => tag`hello ${value}`;
const identicalTemplate = (value) => tag`hello ${value}`;

console.log(template('world').strings === template('bob').strings) // true
console.log(template('world').strings === identicalTemplate('world').strings) // false

All 7 comments

lit-html detected the location where it was called?

It kind of remembers where it's called from, because of how tagge string literals work. In the first example it will make two different templates while in the second case it will only make one template. This means that in the first case it will switch out the custom element and make a new one, while in the second case it will reuse the custom element it made the first time and only update the property. Note that it's changing the property, not the attribute, since it starts with a .. Is your custom element set up to handle the property changing?

should I handle property changes through setter?

remembers where it's called from

How is this implemented? I searched the source code for "try", "throw" and didn't find useful information.

This is a feature of JavaScript tagged template string literals.

When you tag a template string with a function, that function is called with an array of the static string components of the template, and arguments that represent the dynamic values of the template. Each time the tag function is invoked for the same template literal, the string array will be the same object. Lit-html uses this identity to uniquely identify different templates.

const tag = (strings, ...values) => { return {strings, values}};
const template = (value) => tag`hello ${value}`;
const identicalTemplate = (value) => tag`hello ${value}`;

console.log(template('world').strings === template('bob').strings) // true
console.log(template('world').strings === identicalTemplate('world').strings) // false

thanks.

should I handle property changes through setter?

@mantou132 There are a couple of different ways to do this. Using get/set manually every time is straightforward, but may add boilerplate if used often.

class MyElement extends LitElement {
  get foo() {
    return this._foo;
  }
  set foo(value) {
    this._foo = value;
    this.invalidate(); // schedule a re-render
  }
}

If you want to use decorators and class properties (via babel/Typescript), it can help make your code a bit more concise. It basically does the same as above, but it becomes a re-usable pattern.

class MyElement extends LitElement {
  @prop() // automatically calls re-render on changes
  foo;
}

We took inspiration from Polymer/lit-element, and made a base class that can use @prop() and @attr() decorators, for regular properties and values read/written to/from attributes. I suggest taking a look at LitElement, it's pretty popular.

@ruphin The situation seems to have changed now.
@csvn This method is very useful to me because of the change in lit-html.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

depeele picture depeele  路  3Comments

justinfagnani picture justinfagnani  路  3Comments

gkjohnson picture gkjohnson  路  5Comments

erichiggins picture erichiggins  路  4Comments

justinfagnani picture justinfagnani  路  3Comments