Load WordPress Posts in vue.js

Load WordPress Posts in vue.js

by RafaelShouman

HTML

<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="main">
	<h1>WordPress Posts in Vue.js</h1>
	<div class="post">
		<h2 class="post-title">Latest Post Status Posts</h2>
		<p>I wanted to show as simple of a Vue.js app as possible, using WordPress post data. I recently did something similar with React, which you can <a href="https://codepen.io/krogsgard/pen/NRBqPp/">check out</a>.</p>
		<p>I used the Vue.js <a href="https://vuejs.org/examples/commits.html">Github commits example</a> as my primary guide for this demo.</p>
		<p>If you fork this Pen, you can swap out the URL from Post Status to your own website, if it's running <a href="http://v2.wp-api.org">v2 of the WordPress REST API</a>, or WordPress Trunk (developer version).</p>
		<p>The author and featured image data is made available thanks to the <code>?_embed</code> query string, which adds additional information to the return data: author, media, terms, and comments are all included, for example.</p>
		<p>The query for the following posts looks like this: <br>
			<pre>https://poststatus.com/wp-json/wp/v2/posts/?_embed&per_page=3&author=</pre>
			</code>
	<p>The biggest change between this demo and the React demo is this one adds the author toggle, so you can get an idea for using more dynamic data.</p>
	</div>
	<div id="app">
		<div class="author-toggle-wrap post">
			<template v-for="author in authors">
				<div class="author-toggle">
					<input type="radio"
						:id="author"
						:value="author"
						name="author"
						v-model="currentAuthor">
					<label :for="author">Author ID: {{ author }}</label>
				</div>
			</template>
			
		</div>
		
		<div class="post-wrapper">
			<p>Current Author: <code>{{ currentAuthor }}</code></p>
			<template v-for="post in posts">
				<div class="post">
					<h2 class="post-title" v-html="post.title.rendered"></h2>
           <!--<a v-if="post._embedded['wp:featuredmedia'][0].media_details.sizes['large']"-->
					<a...

CSS

@import url(https://fonts.googleapis.com/css?family=Nunito:300);
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  font-weight: 300;
  padding: 2em;
  color: #666;
}

pre {
  overflow: scroll;
  padding: 1em .5em;
  background: #f4f4f4;
}

#main {
  max-width: 30em;
  margin: 0 auto;
  word-wrap: break-word;
}

h1 {
  font-size: 2em;
  margin: 0;
  font-family: Nunito, sans-serif;
  color: #2e3641;
}

a {
  color: #fc781f;
}

.author-toggle-wrap {
  display: block;
  padding: 1em;
  overflow: hidden;
}

.author-toggle {
  display: inline-block;
  width: 40%;
  margin: 5%;
  float: left;
  margin-bottom: 1em;
}

.post {
  font-size: 14px;
  font-weight: 300;
  border-bottom: 1px solid #ddd;
  padding: 2em 0;
}

.post-title {
  display: block;
  font-family: Nunito, sans-serif;
  margin: 0 0 10px 0;
  font-size: 1.5em;
  margin-bottom: 1em;
  color: #2e3641;
}
.post-title a {
  color: #2e3641;
  text-decoration: none;
}
.post-title a:hover {
  color: #fc781f;
}

.excerpt {
  margin: 1em 0;
}

.entry-meta {
  display: block;
  text-transform: uppercase;
  font-family: Nunito, sans-serif;
  margin: 2em 0 1em;
  overflow: hidden;
  line-height: 2;
}
.entry-meta .author-wrap {
  float: left;
  display: inline-block;
  padding: 0;
  text-decoration: none;
  color: #2e3641;
}
.entry-meta .author-wrap:hover {
  color: #fc781f;
}
.entry-meta .author-wrap span {
  display: inline-block;
  padding: .75em 0;
}
.entry-meta .author-wrap .avatar {
  float: left;
  border-radius: 50%;
  margin-right: .5em;
}
.entry-meta .read-more {
  float: right;
}

@media (max-width: 25em) {
  .entry-meta {
    font-size: .75em;
  }
  .entry-meta .avatar {
    width: 32px;
    height: 32px;
  }
}
a.button {
  display: inline-block;
  padding: .75em 1em;
  background: #fc781f;
  color: white;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
  font-family: Nunito, sans-serif;
 ...

JavaScript

'use strict';

var apiURL = '//allotoi.com/wp-json/wp/v2/posts/8';

/**
 * Posts demo with ability to change author
 */

var posts = new Vue({

	el: '#app',

	data: {
		authors: ['1', '590'],
		currentAuthor: '1',
		posts: null
	},

	created: function created() {
		this.fetchData();
	},

	watch: {
		currentAuthor: 'fetchData'
	},

	methods: {
		fetchData: function fetchData() {
			var xhr = new XMLHttpRequest();
			var self = this;
			xhr.open('GET', apiURL + self.currentAuthor);
			xhr.onload = function () {
				self.posts = JSON.parse(xhr.responseText);
	
			};
			xhr.send();
		}
	}
});


//src: post._embedded['wp:featuredmedia'][0].source_url
//source: "//allotoi.com/wp-json/wp/v2/posts/?_embed&per_page=5&author=1"