[Feature] API for rendering VNodes to string
See original GitHub issueWhat problem does this feature solve?
I’ve created a <head>
management system and an awesome feature would be a native way to render VNodes to strings, both in SSR and on client-side
Here’s what I’ve been currently doing in user-land: hello-world.vue
<template>
<master>
<template slot="title">Hello World App</template>
<template slot="description">Meta description here</template>
<template slot="content">
Hello World
</template>
</master>
</template>
<script>
import master from '@/layouts/master'
export default {
components: {
master
}
}
</script>
master.vue
<template>
<servue>
<template slot="head">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ this.$slots.title ? `${ this.$slots.title[0].text } - My App`: `My App` }}</title>
<meta v-if="this.$slots.description" name="description" :content="this.$slots.description[0].text">
<slot name="head"/>
</template>
<template slot="content">
<slot name="content"/>
</template>
</servue>
</template>
<script>
import servue from './servue'
export default {
components: {
servue
}
}
</script>
You can probably see some issues with how this is done, it only accounts for a single text node, and there may be more. Plus, it seems hacky to directly access slot data inside a template
The head is currently being stringified by a small component: servue.vue
<script>
const unaryTags = [
"area",
"base",
"br",
"col",
"embed",
"hr",
"img",
"input",
"keygen",
"link",
"meta",
"param",
"source",
"track",
"wbr"
]
function renderStartTag(VNode) {
let html = `<${VNode.tag}`
if (VNode.data) {
if (VNode.data.attrs) {
let attr = VNode.data.attrs
for (let name in attr) {
if (attr[name] === "") {
html += ` ${name}`
} else {
html += ` ${name}="${attr[name]}"`
}
}
}
}
return html + ">";
}
function isUnaryTag(VNode) {
return unaryTags.indexOf(VNode.tag) > -1
}
function getFullTag(VNode) {
if (!VNode.tag) return VNode.text
let html = renderStartTag(VNode)
if (VNode.children) {
html += getChildren(VNode)
}
if (!isUnaryTag(VNode)) {
html += `</${VNode.tag}>`
}
return html;
}
function getChildren(VNode) {
let html = ""
for (let i in VNode.children) {
let child = VNode.children[i]
html += getFullTag(child)
}
return html
}
export default {
created() {
let VNodes = this.$slots.head
let renderedHead = ""
for (let i in VNodes) {
let VNode = VNodes[i];
renderedHead += getFullTag(VNode)
}
if (this.$isServer) {
this.$ssrContext.head = `<!--VUESERVEHEAD START-->${renderedHead}<!--VUESERVEHEAD END-->`
}else{
let head = document.head
let node
let foundStart = false
let startNode
let children = head.childNodes
for(let node of children){
if(node.nodeType === Node.COMMENT_NODE){
if(node.nodeValue === "VUESERVEHEAD START"){
foundStart = true
startNode = node
continue
}
}
if(foundStart){
if(node.nodeType === Node.COMMENT_NODE){
if(node.nodeValue === "VUESERVEHEAD END"){
break
}
}
head.removeChild(node)
}
}
if(startNode){
let fakeMeta = document.createElement('meta')
startNode.after(fakeMeta)
fakeMeta.outerHTML = renderedHead
}
}
},
render(h){
return h('div', {
class: "servueWrapper"
}, this.$slots.content)
}
};
</script>
This whole process could be simplified by an API exposed by vue. The API already exists, it just needs to be exposed by Vue
What does the proposed API look like?
Vue.renderVNodesToString([VNode])
$vm.renderVNodesToString([VNode])
import { renderVNodesToString } from 'vue'
A few ideas
Issue Analytics
- State:
- Created 4 years ago
- Reactions:22
- Comments:13 (3 by maintainers)
Top Results From Across the Web
How to render a Vue VNode to a String - Stack Overflow
Uses Vue.extend to construct one SVG component constructor, inside render function of the constructor, it renders slots.default .
Read more >Render Function APIs | Vue.js
Creates virtual DOM nodes (vnodes). ... Types are simplified for readability. ... The first argument can either be a string (for native elements)...
Read more >Evan You on Twitter: "@reinink @inertiajs import { render ...
Hey Evan, probably a long shot, but is there any APIs exposed in Vue 3 to help third party libraries render a bunch...
Read more >Snabbdom Renderer - ServiceNow Developers
Creates a vnode for the virtual DOM from a string of HTML. ... element [HTMLElement] - Element to render the view to; handler...
Read more >Inferno API
key : (string|number) unique key within this vNodes siblings to identify it during keyed algorithm. ref : (function) callback which is called when...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@posva it’s slightly different, it’s not for SSR
We need a universal API to render VNodes to a string on the server and the client
What @vedmant said
A canonical example for this could be rendering HTML tooltip for V-Tooltip programatically.
So it’s not that much of a niche use-case.