Reputation: 2071
I’v been searching for hours now and didn’t find anything close to my use case.
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
article {
margin: 8px 0;
background: #eee;
padding: 20px;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<!-- server rendered -->
<div id="app">
<h2>Freelance list</h2>
<article>
<h3>louane</h3>
<p>
City : <strong>courbevoie</strong>
<br> Phone : <strong>05-36-23-51-89</strong>
</p>
</article>
<article>
<h3>indra</h3>
<p>
City : <strong>rheden</strong>
<br> Phone : <strong>(354)-415-2419</strong>
</p>
</article>
<article>
<h3>angelo</h3>
<p>
City : <strong>montpreveyres</strong>
<br> Phone : <strong>(883)-474-9314</strong>
</p>
</article>
<a href="/prev-link">prev</a>
<a href="/next-link">next</a>
</div>
<!-- server rendered -->
// fake url link, normally this would be taken from the href or something
var url = 'https://randomuser.me/api/?seed=abc&results=3&page=';
var page = 1;
var $articles = $('.articles');
var tpl = $articles.children().eq(0).clone();
$('.prev').click(function(e) {
e.preventDefault();
if (page <= 1) {
return
}
page--;
$.getJSON(url + page)
.done(onReqDone);
});
$('.next').click(function(e) {
e.preventDefault();
page++;
$.getJSON(url + page)
.done(onReqDone);
});
function onReqDone(res) {
$articles.html('');
res.results.forEach(function(user) {
var $node = tpl.clone();
$node.find('h3').text(user.name.first);
$node.find('strong:eq(0)').text(user.location.city);
$node.find('strong:eq(1)').text(user.phone);
$articles.append($node);
window.scroll(0, 0);
});
}
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
article {
margin: 8px 0;
background: #eee;
padding: 20px;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- server rendered -->
<div id="app">
<h2>Freelance list</h2>
<div class="articles">
<article>
<h3>louane</h3>
<p>
City : <strong>courbevoie</strong>
<br> Phone : <strong>05-36-23-51-89</strong>
</p>
</article>
<article>
<h3>indra</h3>
<p>
City : <strong>rheden</strong>
<br> Phone : <strong>(354)-415-2419</strong>
</p>
</article>
<article>
<h3>angelo</h3>
<p>
City : <strong>montpreveyres</strong>
<br> Phone : <strong>(883)-474-9314</strong>
</p>
</article>
</div>
<a href="/prev-link" class="prev">prev</a>
<a href="/next-link" class="next">next</a>
</div>
<!-- server rendered -->
Any ideo on how to do it ? Here are my tries : https://jsfiddle.net/7270zft3/2/ : problem, it doesn’t remove the old dom
PS : Before anyone talks about SSR with Vue ou just doing an SPA, here’s why i cant :
Upvotes: 1
Views: 1114
Reputation: 2071
Someone on the Vue forum found a good approach close to what was posted here but suited better my need : https://forum.vuejs.org/t/using-vue-to-enhance-existing-multi-page-server-rendered-classic-web-app/30934/20
Upvotes: -1
Reputation: 43881
An example of hydration. I wasn't able to get Vue to stop warning me that my generated HTML didn't match the original; it's not critical. In development, Vue will "bail and do a full render", but in production it will leave the pre-rendered. You just want to be sure they match, so that when it does update, it's what you expect.
I left jQuery in for the getJSON
. Other than that, it's jQuery free.
// fake url link, normally this would be taken from the href or something
var url = 'https://randomuser.me/api/?seed=abc&results=3&page=';
var page = 1;
$.getJSON(url + page).done((res) => {
const articles = res.results;
new Vue({
el: '#app',
template: `
<div id="app">
<h2>Freelance list</h2>
<div class="articles">
<article v-for="article in articles">
<h3>{{article.name.first}}</h3>
<p>
City : <strong>{{article.location.city}}</strong>
<br> Phone : <strong>{{article.phone}}</strong>
</p>
</article>
</div>
<a href="/prev-link" class="prev" @click.prevent="--page">prev</a>
<a href="/next-link" class="next" @click.prevent="++page">next</a>
</div>
`,
data: {
page,
url,
articles
},
methods: {
getPage() {
$.getJSON(this.url + this.page)
.done((res) => {
this.articles = res.results;
});
}
},
watch: {
page() {
this.getPage();
}
}
});
});
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
article {
margin: 8px 0;
background: #eee;
padding: 20px;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app" data-server-rendered="true">
<h2>Freelance list</h2>
<div class="articles">
<article>
<h3>louane</h3>
<p>
City : <strong>courbevoie</strong>
<br> Phone : <strong>05-36-23-51-89</strong>
</p>
</article>
<article>
<h3>indra</h3>
<p>
City : <strong>rheden</strong>
<br> Phone : <strong>(354)-415-2419</strong>
</p>
</article>
<article>
<h3>angelo</h3>
<p>
City : <strong>montpreveyres</strong>
<br> Phone : <strong>(883)-474-9314</strong>
</p>
</article>
</div>
<a href="/prev-link" class="prev">prev</a>
<a href="/next-link" class="next">next</a>
</div>
<!-- server rendered -->
Upvotes: 1
Reputation: 19194
You can attach a DOM ref to the server rendered content and then just as in jQuery, just clear the contents to the DOM element.
You need to perform this action only once, so you can may be add checks to see if your DOM ref is empty if page === 1
new Vue({
el: "#app",
data: {
users: null,
page: 1
},
methods: {
loadData: function(prev) {
var page = this.page
if (prev) {
page--
} else {
page++
}
fetch('https://randomuser.me/api/?seed=abc&results=3&page=' + page)
.then(res => res.json())
.then(data => {
this.$refs.serverContent.innerHTML = '';
this.users = data.results
this.page = page
window.scroll(0, 0)
})
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
article {
margin: 8px 0;
background: #eee;
padding: 20px;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<h2>Freelance list</h2>
<div ref="serverContent">
<article>
<h3>louane</h3>
<p>
City : <strong>courbevoie</strong>
<br> Phone : <strong>05-36-23-51-89</strong>
</p>
</article>
<article>
<h3>indra</h3>
<p>
City : <strong>rheden</strong>
<br> Phone : <strong>(354)-415-2419</strong>
</p>
</article>
<article>
<h3>angelo</h3>
<p>
City : <strong>montpreveyres</strong>
<br> Phone : <strong>(883)-474-9314</strong>
</p>
</article>
</div>
<!-- Vue part -->
<!-- how to plug Vue to handle the pagination ? -->
<article v-for="user in users">
<h3>{{ user.name.first }}</h3>
<p>
City : <strong>{{ user.location.city }}</strong>
<br> Phone : <strong>{{ user.phone }}</strong>
</p>
</article>
<!-- Vue part -->
<button v-show="page > 1" @click="loadData(true)">prev</button>
<button @click="loadData()">next</button>
</div>
<!-- server rendered -->
But to do it Vue style, it is advised that you remove the rendering of first page from the server and let Vue handle data-fetching by itself so that Vue can use the data
it stores as the source of truth instead of manipulating the DOM.
Upvotes: 1