New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose/add VNode creation from data without render function #9283

Open
donnysim opened this Issue Jan 7, 2019 · 0 comments

Comments

Projects
None yet
1 participant
@donnysim
Copy link

donnysim commented Jan 7, 2019

What problem does this feature solve?

Could we expose a way to create a VNode from an object without having to import VNode directly from vue/core/vdom/vnode and have to deal with flowjs type stripping? On my latest project I began experimenting with JSX syntax and the flexibility and things that it allows (or would allow) to do are really interesting compared to SFC templates.

The current problem is that sometimes you need to merge some additional listeners, but it becomes a normal object instead of VNode and so you lose the simple JSX render syntax like {this.show && this.mergedVNode}.

Typically this would not be a big problem because you could take the tag name from the VNode with something like:

function getVNodeTag(nodeData) {
  if (!nodeData) {
    return nodeData;
  }

  if (nodeData.componentOptions) {
    return nodeData.componentOptions.tag;
  }

  return nodeData.tag;
}

and then use it in render:

const Tag = getVNodeTag(this.mergedVNode);
...
{this.show && <Tag {...this.mergedVNode}/>}

But it falls short when the node contains a Ctor constructor component, which does not really have a tag you could use for render. This could be circumvented by introducing a wrapper element around the passed VNode, but it's not ideal in some cases where it could break styling, positioning etc..

What JSX allows is passing a formatted text into a function, for example notifications: this.$notifications.info(<h1>The file <strong>{this.file.name}</strong> was deleted.</h1>);. Or it could be the whole component (but the issue with tag name rises):

this.$notifications.show(<CustomNotification type="error" onClose={this.onNotificationClose}>
  <h1>The file <strong>{this.file.name}</strong> was deleted.</h1>
</CustomNotification>);

While yes, it will not be reactive in such cases (this.file.name), but it is not intended to be. It provides a more expressive way to show a customized message without having to resort to in-template component and portal to position it, or config objects.

What does the proposed API look like?

Maybe have an utility in Vue.util? Vue.util.createVNode(nodeData)? which basically all it does is return new VNode(nodeData);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment