I would like to use Vue (v2) to manage parts of an HTML page, but do it in such a way that if the user does not have javscript, they still get a nice page.
e.g. The server might output:
<div id="rootAppContainer">
...
<article is="foo" >
<h1>Something cool</h1>
<p>Here's a great article.</p>
</article>
...
</div>
Which is fine as a fallback. But I'd like Vue to mount the article and replace it with something better, e.g.
<article>
<p v-show="showTeaser" >{{teaser}}</p>
<div v-show="!showTeaser" >
<h1>{{title}}</h1>
<p>Here you go:</p>
<p>{{body}}</p>
</div>
</article>
To do this, I'd like to be able to parse the pre-vue content of the element that's getting mounted to extract the view-model's data
that will then be formatted by its template.
I thought I could do this with lifecycle hooks, or the component's data method, but I can't find any way to get a reference to the soon-to-be-mounted node; until it's too late (i.e. in mounted
when it's already been replaced).
https://codepen.io/artfulrobot/pen/GOGBWQ?editors=1010
First, I should say that you should look into server side rendering.
However, if you are stuck without SSR, you could parse the DOM before the Vue is created, and replace the articles with components.
Here is an example.
console.clear()
let root = document.querySelector("#rootAppContainer")
for (let article of root.querySelectorAll('article')){
let title = article.querySelector("h1").textContent
let body = article.querySelector("p").textContent
let foo = document.createElement("foo")
foo.setAttribute("title", title)
foo.setAttribute("body", body)
root.replaceChild(foo, article)
}
const app = new Vue({
el: '#rootAppContainer',
components: {
foo: {
props:["title", "body"],
data: function() {
return {
showTeaser: true,
};
},
computed: {
teaser: function() {
return "ooh, you won't believe this..." + this.title;
}
},
template: `
<article>
<p v-show="showTeaser" >{{teaser}}</p>
<div v-show="!showTeaser" >
<h1>{{title}}</h1>
<p>Here you go:</p>
<p>{{body}}</p>
</div>
</article>
`,
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script>
<div id="rootAppContainer">
<h2>some content before articles</h2>
<article>
<h1>Something cool</h1>
<p>Here's a great article.</p>
</article>
<h2>some content between articles</h2>
<article>
<h1>Another cool thing</h1>
<p>Here's a great article.</p>
</article>
<article>
<h1>And lastly something cool</h1>
<p>Here's a great article.</p>
</article>
<h2>some content after articles</h2>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With