基于wordpress的headless CMS构建Vue单页应用
特别说明:本文翻译自Build a Vue.js SPA on Top of Headless WordPress,如需更多了解,请前往原文阅读。
难以置信,我又要开始写关于wordpress的东西了。
开个玩笑,事实上,在我最后一次使用wordpress的rest api时,我还觉得它非常的酷。
看到如此庞大的网络产业向现代趋势和新范式开放,还真是让人耳目一新。所以,我想知道如果把我最喜欢的前端框架Vue和wordpress结合起来会不会很有趣呢?
事实证明,这当然是非常有趣的。
在本文中,我将对这个技术栈进行更深入的讲解。本教程将涵盖以下几个方面:
- 在wordpress中使用自定义字段来创建模型。
- 将WP REST API构建成自定义端点。
- 创建一个Vue单页面应用。
- 将这个应用进行托管。
首先,明确一下使用wordpress作为一个headless CMS。
在用一个具体的wordpress例子进行深入研究前,先确保我们对Headless CMS的理解是一致的。
一直到几年前,我们还习惯于使用传统的CMSs,它们管理前端和后端以及前端和后端之间所有的东西,包括前端的页面、后端的数据、角色权限等等。然而,由于前端的现代化的兴起,也引发了这一重大的转变。前端现代化产生的生态圈中,根本没有多余的位置存放这些老旧、单一的CMSs,替代它们的将会是静态站点生成器、以API为中心的微服务和无服务架构。
但是,这并不意味着想wordpress这样的东西就该退出历史舞台了,这只是说明它们需要谋求变革,它们不应该在管理网站的所有东西,因为现在有很多工具在某些方面做的更好。
所以,为什么不用wordpress来做它真正擅长的东西呢?而这正是自wordpress4.7发布的WP REST API支持的。它允许在wordpress后台注入的内容被用于前端应用,不论涉及到什么技术。
这将是一场游戏的变革。
我敢肯定,如果你是一个只有一点点wordpress经验的开发者,你应该已经注意到这场变革带来的新的机遇了。
顺便说一下,开发人员多年来一直抱怨的问题,WordPress的主要缺点:开发很不自由,而且模板定制很麻烦。但是如果只使用WordPress作为后台来开发应用,那这些问题不仅可以抛之脑后了,还会在开发速度上得到一个大的提升:
- 开发人员可以在模块化的自由地使用他们喜欢的工具,这将使得项目具有高可扩展性,而且,这样也会带来更好的性能。
- 不再需要去处理WP的模板,将它插入到你喜欢的前端,而无需担心覆盖基于php的模板,因为从头开始构建强大的用户界面要容易得多,然后就可以使用WordPress的数据了。
为什么会选择在wordpress中使用Vue呢?
在过去,把wordpress和JS框架结合在一起以供我们在应用程序中使用WordPress也许会给你带来很大的困难,但是,想想多设备应用程序、物联网、先进的网络应用程序和其他现代实践。
除了我已经在我的第一个WP headless demo中使用了React这一事实外,我还有很多理由向那些寻找合适前端框架的人推荐Vue.js。
你可能听到人们讨论Vue最多的是它的模块化、速度和高性能。我想说这些都是绝对正确的,你可以放心,我不是在这里胡说,在Snipcart,甚至使用它来支持我们最新版本的购物车。
而且,这种新兴技术的构建工具一天比一天成熟。就像JavaScript生态系统一样,Vue的生态圈也在不断扩大。现在几乎任何类型的前端项目都有基于它的工具。以下是你应该关注的主要问题:
Nuxt: 一个引人注目的静态站点生成、单页应用程序(SPA)开发和服务器端渲染的框架。在本教程中,我们使用它在headless CMS的基础上构建了一个静态站点。
Gridsome: 相当于 Vue中的Gatsby(基于React的开源框架)。由GraphQL支持从任何来源获取数据,包括headless CMS。它可以生成渐进式Web应用程序(PWA)。
VuePress: 一个极简的基于Vue的静态网站生成器,拥有完整的学习文档和博客。
SEO是个问题吗?
SEO是最需要被优化的,以传统的方式使用WordPress的一个好处是你不用太担心SEO。因此,当我们听说JS框架在seo方面不是很好时,我可以理解为什么人们不愿意使用它。
但是让我们彻底澄清一下。实际上,如果你处理得当,你可以用Vue取得很好的SEO结果。使用Nuxt.js进行服务器端呈现是一种方法,但是您也可以使用简单的预渲染服务,就像我们在这里所做的一样。
然后,更好的性能和用户体验实际上将会提高你的SEO效果。
教程: Headless WordPress 绑定到一个vue单页应用
主要内容:
我们的团队正在扩张,但是这其中也包含了在一些成员居住的城市扩张。所以假设我们很难在按比例计算时去记住每个成员的位置,我将创建一个应用程序,用来跟踪每个成员的位置,并在交互式地图上标记出他们的位置坐标。
我将向你展示如何制作一个响应式的Vue单页应用来实现这个功能。后端部分非常类似我之前的一篇wordpress与React结合使用的文章中提到的,但这次,我将以不同的方式在vue单页应用中使用这些数据。
预备条件:
一个正在运行的wordpress实例
vue基础
一个免费的MapBox账号
1、在wordpress中创建自定义字段模板
让我们直接进入WordPress管理页面。我将使用ACF (Advanced Custom Fields)插件来演示如何创建自定义字段模板。这个插件允许你添加自定义字段到原生WordPress实体中,比如post。它经过了较为完整的测试,非常稳定,并且在向页面添加自定义数据时可以快速启动。您可以使用WordPress仪表板中的Plugins选项卡轻松地安装它。下面就是你需要下载的这个插件:
对于这个例子,您将需要四个字段:两个坐标、一个名称和一个图像。下面是它在仪表板上的样子:
现在你可以添加自定义数据到你的WordPress文章中,让我们使用它们来创建标记来显示团队成员的居住位置。以下是新创建的帖子列表:
2、构建自定义端点
现在你已经拥有了你想要的数据,你还需要将它向公众开放,以便可以通过REST API来访问到这些数据。
为此,还需要构建一个自定义端点。打开WordPress文件夹并打开functions.php文件,这是你将注册新端点的地方。将下面的几行代码添加达到文件末尾:
function markers_endpoint( $request_data ) {
$args = array(
'post_type' => 'post',
'posts_per_page'=>-1,
'numberposts'=>-1
);
$posts = get_posts($args);
foreach ($posts as $key => $post) {
$posts[$key]->acf = get_fields($post->ID);
}
return $posts;
}
add_action( 'rest_api_init', function () {
register_rest_route( 'markers/v1', '/post/', array(
'methods' => 'GET',
'callback' => 'markers_endpoint'
));
});
add_action方法创建自定义端点,并通过rest_api_init钩子注册它。调用端点后,将执行回调,并在acf字段下返回你的自定义字段。
以下将是你在GET请求后得到的返回结果:
[
{
"ID": 19,
"post_author": "1",
"post_date": "2019-03-14 15:48:40",
"post_date_gmt": "2019-03-14 19:48:40",
"post_content": "",
"post_title": "Chuck",
"post_excerpt": "",
"post_status": "publish",
"comment_status": "open",
"ping_status": "open",
"post_password": "",
"post_name": "chuck",
"to_ping": "",
"pinged": "",
"post_modified": "2019-03-14 15:48:41",
"post_modified_gmt": "2019-03-14 19:48:41",
"post_content_filtered": "",
"post_parent": 0,
"guid": "http:\/\/localhost\/wordpress\/?p=19",
"menu_order": 0,
"post_type": "post",
"post_mime_type": "",
"comment_count": "0",
"filter": "raw",
"acf": {
"Name": "Chuck",
"image": "http:\/\/localhost\/wordpress\/wp-content\/uploads\/2019\/03\/charles-snipcart.png",
"longitude": "49.8951",
"Latitude": "97.1384"
}
}, ...
]
3、创建Vue单页应用
让我们即刻将这些新出炉的数据用起来。
首先构建一个vue项目,如果你还不知道如何构建vue项目或者不知道如何使用相关插件,请先移步到这里了解如何构建vue项目这里了解如何构建vue项目。以下内容我们将假设你已经会使用vue并对相关的类容有一定的了解。
接着,创建你的项目:vue create markers。
首先要做的是在App组件中请求API并获取数据。为此,只需向组件添加以下声明:
<template>
<div id="app">
<div class="badge-container">
<div v-for="badge in markers" :key="badge.name">
<Badge :name="badge.name" :image="badge.image" />
</div>
</div>
<Map v-if="markers.length > 0" :markers="markers" />
</div>
</template>
<script>
import Badge from './components/Badge.vue'
import Map from './components/Map.vue'
export default {
name: 'app',
data(){
return {
markers: []
}
},
components: {
Badge,
Map
},
mounted(){
fetch('https://wordpress-vue.herokuapp.com/index.php/wp-json/markers/v1/post')
.then((r) => r.json())
.then((res) => this.markers = res.map(x => x.acf));
}
}
有了数据之后,让我们创建第一个组件(在components文件夹中),命名为Badge。代码如下:
<template>
<div class="badge" :id="name">
<img :src=img width=500/>
<h2>{{ name }}</h2>
</div>
</template>
<script>
export default {
name: 'Badge',
props: {
Name: String,
Image: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
让我们回到应用程序组件,导入Badge组件,并在组件对象中注册它:
components: {
Badge
}
接着,我们再创建一个新 组件Map.vue。在这里,我将使用Mapbox来显示地图。他们有免费的版本,整洁和完整的文档…我不能要求更多了。一旦您创建了一个帐户,您将能够直接访问仪表板主页地址:https://account.mapbox.com/。
首先,在你的index.html文件中直接引入Mapbox的JS和CSS:
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.53.1/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.53.1/mapbox-gl.css' rel='stylesheet' />
然后像下面这样定义Map组件:
<template>
<div>
<div id='map' class='map'> </div>
</div>
</template>
<script>
export default {
name: 'Map',
mounted(){
window.mapboxgl.accessToken = "{YOUR_MAPBOX_ACCESS_TOKEN}";
var map = new window.mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/dark-v9',
center: [-81.4608, 48.4758],
zoom: 4
});
map.on('load', (() => {
this.markers.forEach(function(marker) {
var el = document.createElement('div');
el.className = 'marker';
new window.mapboxgl.Marker(el)
.setLngLat([parseFloat(marker.latitude), parseFloat(marker.longitude)])
.addTo(map);
});
this.markers.forEach((x) => {
document.getElementById(x.name)
.addEventListener('click', () => {
map.flyTo({
center: [parseFloat(x.latitude), parseFloat(x.longitude)],
zoom: 9
})
;}
)
})
}).bind(this));
},
props: {
markers: Array
}
}
</script>
<style>
.marker {
background-image: url('./../assets/mapbox-icon.png');
background-size: cover;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
}
</style>
正如你所看到的,Map组件的props只需要接受一个markers属性,这个属性是一个包含所有信息的数组。你需要将自己的accessToken绑定上,然后给map对象绑定load事件,这样就能确保在map对象加载完毕后才开始读取并展现markers数组中的数据。
接着用css做一个定位的标记,并把它添加到map中。最后你要做的就是给每一个Badge绑定点击事件,以实现点击对应的Badge时,地图能定位到对应的位置。
到这里我们就完成了整个应用的功能,你可以在wordpress后台添加或删除你的自定义字段,你的应用会自动加载你修改的数据。
总结:
通过将wordpress作为一个headless CMs,你只需要专注于你的前端界面的开发,而不需要单独去维护一个服务器,你的数据可以保存在wordpress中,你也可以通过wordpress的控制面板对你的数据进行操作,这种方式能让你快速开发出一个全新的网站。如果你对此感兴趣,你还可以了解到更多wordpress的东西,甚至你不需要自己去写php的代码了,很多插件都可以解决本例中php代码的部分。