antonmedv / monkberry

Monkberry is a JavaScript library for building web user interfaces
https://monkberry.js.org
MIT License
1.49k stars 78 forks source link

Handling of lifecycle events and keyed lists? #17

Open trueadm opened 8 years ago

trueadm commented 8 years ago

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 :)

antonmedv commented 8 years ago

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.

trueadm commented 8 years ago

@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.

antonmedv commented 8 years ago

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

Can you show some example there keyed is important?

trueadm commented 8 years ago

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.

antonmedv commented 8 years ago

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.

trueadm commented 8 years ago

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.

antonmedv commented 8 years ago

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

trueadm commented 8 years ago

@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.

antonmedv commented 8 years ago

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.

trueadm commented 8 years ago

@elfet good to hear :)

francescoagati commented 8 years ago

morphdom use id for keyed list. https://github.com/patrick-steele-idem/morphdom/blob/master/src/index.js#L342

francescoagati commented 7 years ago

@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