使用 Vue 增强现有的多页面/服务器呈现/经典网络应用程序
Using Vue to enhance existing Multi page / server rendered / classic web app
我已经搜索了几个小时,但没有找到任何与我的用例相近的东西。
- 我有一个用JAVA
制作的经典/多页面/服务器呈现的电子商务网站
- 我有一个页面,服务器在其中呈现带有分页的产品列表
- 今天,我使用jQuery做分页,给用户更好的加载体验
- 在我的服务器上,如果请求是 AJAX 则发送 json 响应,否则我会呈现正常的 html 视图
- 使用 jQuery 和 vanilla 真的很容易,使用 Vue 似乎行不通,因为 Vue 的 v-for 和其他模板绑定直接替换了服务器渲染的模板...
- 服务器会呈现这个:
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 -->
- 我希望能够用 Vue 做这样的事情 :
// 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 -->
关于如何操作的任何想法?这是我的尝试:
https://jsfiddle.net/7270zft3/2/ : 问题,它没有删除旧的 dom
PS :
在任何人谈论 Vue 的 SSR 或者只是做一个 SPA 之前,这就是我不能的原因:
- 这个电子商务网站不可能完全用一个单页应用程序重新制作,它给我们带来的好处会花费太多的时间和金钱
- 这个电子商务需要 SEO 来继续推动流量,就像任何电子商务顺便说一句
- 如果 Vue 真的可以像 jQuery 那样使用(这就是我们押注 Vue 的原因),我们应该可以做到这一点而无需进行完全重写
- 即使我们有时间重写 SPA,我们也不能使用 SSR,因为我们的后端是用 JAVA 制作的,而且 SSR 似乎只适用于 node 而 PHP 使用 v8js 模块
您可以将 DOM ref 附加到服务器呈现的内容,然后就像在 jQuery 中一样,只需将内容清除到 DOM 元素。
您只需执行此操作一次,因此您可以添加检查以查看您的 DOM ref 是否为空 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 -->
但是要用Vue风格,建议你把第一页的渲染从服务器端去掉,让Vue自己处理data-fetching,这样Vue就可以使用它存储的data
作为真相的来源,而不是操纵 DOM。
hydration的例子。我无法让 Vue 停止警告我生成的 HTML 与原始文件不匹配;这并不重要。在开发中,Vue 将 "bail and do a full render",但在生产中它将保留 pre-rendered。您只想确保它们匹配,这样当它确实更新时,它就是您所期望的。
我把 jQuery 留给了 getJSON
。除此之外,它 jQuery 免费。
// 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 -->
Vue 论坛上的某个人发现了一个与此处发布的内容接近但更适合我的需要的好方法:https://forum.vuejs.org/t/using-vue-to-enhance-existing-multi-page-server-rendered-classic-web-app/30934/20
我已经搜索了几个小时,但没有找到任何与我的用例相近的东西。
- 我有一个用JAVA 制作的经典/多页面/服务器呈现的电子商务网站
- 我有一个页面,服务器在其中呈现带有分页的产品列表
- 今天,我使用jQuery做分页,给用户更好的加载体验
- 在我的服务器上,如果请求是 AJAX 则发送 json 响应,否则我会呈现正常的 html 视图
- 使用 jQuery 和 vanilla 真的很容易,使用 Vue 似乎行不通,因为 Vue 的 v-for 和其他模板绑定直接替换了服务器渲染的模板...
- 服务器会呈现这个:
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 -->
- 我希望能够用 Vue 做这样的事情 :
// 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 -->
关于如何操作的任何想法?这是我的尝试: https://jsfiddle.net/7270zft3/2/ : 问题,它没有删除旧的 dom
PS : 在任何人谈论 Vue 的 SSR 或者只是做一个 SPA 之前,这就是我不能的原因:
- 这个电子商务网站不可能完全用一个单页应用程序重新制作,它给我们带来的好处会花费太多的时间和金钱
- 这个电子商务需要 SEO 来继续推动流量,就像任何电子商务顺便说一句
- 如果 Vue 真的可以像 jQuery 那样使用(这就是我们押注 Vue 的原因),我们应该可以做到这一点而无需进行完全重写
- 即使我们有时间重写 SPA,我们也不能使用 SSR,因为我们的后端是用 JAVA 制作的,而且 SSR 似乎只适用于 node 而 PHP 使用 v8js 模块
您可以将 DOM ref 附加到服务器呈现的内容,然后就像在 jQuery 中一样,只需将内容清除到 DOM 元素。
您只需执行此操作一次,因此您可以添加检查以查看您的 DOM ref 是否为空 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 -->
但是要用Vue风格,建议你把第一页的渲染从服务器端去掉,让Vue自己处理data-fetching,这样Vue就可以使用它存储的data
作为真相的来源,而不是操纵 DOM。
hydration的例子。我无法让 Vue 停止警告我生成的 HTML 与原始文件不匹配;这并不重要。在开发中,Vue 将 "bail and do a full render",但在生产中它将保留 pre-rendered。您只想确保它们匹配,这样当它确实更新时,它就是您所期望的。
我把 jQuery 留给了 getJSON
。除此之外,它 jQuery 免费。
// 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 -->
Vue 论坛上的某个人发现了一个与此处发布的内容接近但更适合我的需要的好方法:https://forum.vuejs.org/t/using-vue-to-enhance-existing-multi-page-server-rendered-classic-web-app/30934/20