antonmedv/monkberry

Handling of lifecycle events and keyed lists?

trueadm opened this issue · 12 comments

Is there any plans to bring lifecycle events to Monkberry (both on components and elements)? Furthermore, is there any plans to support keyed lists, as currently the update process of children in Monkberry seems to be destructive. Having support for keys on elements would resolve this issue.

Good work by the way, keep it up :)

Hi,

Now I do not planning adding lifecycle events, but you can use something like this:

class Component extends Template {
  update(state) {
    this.shouldComponentUpdate(state);
    // ...
    super.update(state);
    // ...
    this.after(state);
  }
}

Keyed lists can bring some optimizations, but even without them Monkberry is fast.

@Elfet Keyed lists is not about performance. It's main importance is preservation of internal DOM state. It prevents input, video, iframe and custom elements etc from getting removed/added if they move about in an array. This is a hugely important feature for any UI library.

I see, will think how it's possible to implement keyed feature for loops.

Can you show some example there keyed is important?

I brief example, imagine this:

<div>
    <input>
    <div>something</div>
    <div>something else</div>
</div>

I've started typing something into the input field and I've got a focus on the field too, then an update comes in whilst I'm doing that. The update says to move the elements around so that it becomes:

<div>
    <div>something</div>
    <div>something else</div>
    <input>
</div>

I'd expect the input element to move two places down in the array of children and my focus and value on the input to be unchanged. Except, it can't do that unless it knows how to move them around and that's where keys can be highly effective.

I see, but Monkberry does not use any virtual-dom model, it is simple not possible to create template there <input> tag should be moved to the end of list (what is correct for vdom where you can expect anything to render).

Monkberry used a different approach, there no cases then you need to reorder element. In Monkberry you can use only {% if %} and {% for %} tags:

<div>
    {% if showInput %}
      <input>  
    {% endif %}
    <div>something</div>
    <div>something else</div>
<div>

There only one case there keyed thinks may be used — it's loops.

<ol>
  {% for list %}
    <li key={{ id }}>
  {% endfor %}
</ol>

And here it will be nice to have such functionality. Or maybe with another syntax:

{% for item of list keyed item.id %}

But at this point i think it will complicate everything.

I'm going to write an article about how Monkberry works later.

My above example was that of using lists, sorry if I didn't make that clear. Still, you need key support in Monkberry for real-world use if anyone plans to use much of the DOM spec in the way it was intended to be used.

Monkberry is production ready, it's used already in http://www.jetradar.com and https://www.travelpayouts.com

@Elfet That's good to see. Do those sites have have instances of large lists of items containing stateful DOM elements?

Scenario: someone tries to use Monkberry for something like a news feed, that might have ~20 items in at a time and works like an infinite scrolling list. The newsfeed items include video and iframes of user content (imagine a Facebook newsfeed). If the array of data from the model changes as they scroll and items change order on the feed, the videos and iframes are going to get reset and scrapped/rebuilt without having a concept like keys.

We have large lists of airline tickets.

If using large mutating list of iframes/videos/inputs you will lost state, it that case you need to do some hand work. Example: https://jsfiddle.net/medv/5ob123e4/
So, i'm planning to implement keys for loops.

@Elfet good to hear :)

@trueadm @Elfet i think that the beauty of monkberry is his simplicity. So when there must be another type of render for best performance for some use case (like a virtual dom) this can be embed with a monkberry directive.
Image that we can implement a dynamic list with a fast virtual dom like inferno or snabbdom, wrap it inside a monkberry directive an use inside a monkberry template.

For example imagine big_list is a directive that pass the data players to a virtual dom and render the output of the virtual dom

<h1>{{title}}</h1>
<div :big_list={{players}}></div>

and we update only the data of players

   view.update({players:[.....]})

we can have the best of 2 world. Like vue.js 2.0 that is an hybrid of double way data binding and virtual dom