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

Render without a parameter 'el' #47

Open paleo opened 6 years ago

paleo commented 6 years ago

My main use case is with a template with one root element. For example:

<section>
  <h1>{{ title }}</h1>
  <content>{{ body }}</content>
</section>

Then, I need to create the DOM element as a detached element, without to insert it immediately. Currently I use the following code:

let view = render(template, document.createElement("div")) // → an unused '<div>' is created
let rootElement = view.nodes[0]

And here is what I would like to do:

let view = render(template)
let rootElement = view.singleNode

I suggest to:

  1. Make the parameter el optional, or create a new exported function renderDetached without this parameter;
  2. Add an ES5 getter named singleNode, that throws an Error when view.nodes.length !== 1, and returns the single node otherwise. Or a classic member singleNode that is undefined when view.nodes.length !== 1.

I think I could implement it but I saw you have started a huge redesign…

(Regarding your redesign, I suggest you to leave Babel for the server part. Recent versions of Node.js can work with ES 6, 7, 8, except for the import / export.)

antonmedv commented 6 years ago

Does other ui libs like react or vue support detached rendering?

I think we can figure out something for new version of monkberry.

paleo commented 6 years ago

Does other ui libs like react or vue support detached rendering?

Yes, at least for React.

Here is the first example on reactjs.org with the JSX syntax:

class HelloMessage extends React.Component {
  render() {
    return (
      <div>
        Hello {this.props.name}
      </div>
    );
  }
}

ReactDOM.render(
  <HelloMessage name="John" />,
  mountNode
);

After compilation to JS:

class HelloMessage extends React.Component {
  render() {
    return React.createElement(
      "div",
      null,
      "Hello ",
      this.props.name
    );
  }
}

ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), mountNode);

The call to React.createElement is the equivalent to Monkberry.render. It creates virtual DOM elements then returns them.

Notice: ReactDOM.render is NOT equivalent to Monkberry.render. It is something Monkberry doesn't need. ReactDOM.render converts the virtual DOM objects to real DOM objects.

antonmedv commented 6 years ago

Okay, but lets wait until I finish v5 as it will have a little different abstractions.