Skip to content

Instantly share code, notes, and snippets.

@hideki-a
Last active May 2, 2017 23:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hideki-a/44882a7ab602ea59251f7e1933b1f897 to your computer and use it in GitHub Desktop.
Save hideki-a/44882a7ab602ea59251f7e1933b1f897 to your computer and use it in GitHub Desktop.
Forked from takanashi66/vue_rest.
'use strict';
Vue.component('search-form', {
props: {
query: String,
},
template: `
<form class="search" action="#" @submit.prevent="searchPosts">
<input type="search" :value="query"><input type="submit" value="検索">
</form>
`,
methods: {
searchPosts() {
const query = this.$el.querySelector('input[type="search"]').value;
this.$emit('search', query);
},
},
})
Vue.component('entry-list', {
props: {
apiUrl: String,
postsData: Object,
config: Object,
},
template: `
<div class="posts">
<div v-if="postsData.posts && postsData.posts.length > 0" class="list">
<div class="post" v-for="post of postsData.posts">
<h2><a :href="post.link">{{post.title.rendered}}</a></h2>
<p>{{post.excerpt.rendered | stripTags}}</p>
<div v-if="post.thumbnail" class="thumbnail"><img :src="post.thumbnail" alt="" style="width: 150px;"></div>
</div>
</div>
<div v-else-if="postsData.totalPosts == 0">投稿がありません。</div>
<div v-if="hasNextPosts" class="load">
<button @click="loadNextPage">続きを読む</button>
</div>
</div>
`,
computed: {
hasNextPosts() {
if (this.postsData.totalPosts > this.postsData.posts.length) {
return true;
}
return false;
},
},
methods: {
loadNextPage() {
this.$emit('loadNext');
},
},
filters: {
stripTags: (html) => {
return html.replace(/(<([^>]+)>)/ig, '');
}
},
});
const vm = new Vue({
el: '#app',
data() {
return {
apiUrl: 'http://wordpress.localhost/wp-json/wp/v2',
postsData: {
posts: [],
totalPosts: null,
currentPage: 0,
query: null,
},
config: {
postsPerPage: 2,
},
}
},
template: `
<div>
<search-form :query="postsData.query" @search="searchPosts"></search-form>
<entry-list :apiUrl="apiUrl" :postsData="postsData" :config="config" @loadNext="loadNextPage"></entry-list>
</div>
`,
methods: {
_setImageUrlsToData(posts) {
posts.forEach((post, index) => {
const content = post.content.rendered;
const regex = /wp-image-(\d+)/g;
const matched = regex.exec(content);
const imageId = matched && matched[1] ? matched[1] : null;
if (imageId) {
const arrayIndex = this.config.postsPerPage * (this.postsData.currentPage - 1) + index;
fetch(this.apiUrl + '/media/' + imageId)
.then(response => {
return response.json();
})
.then(media => {
this.postsData.posts[arrayIndex].thumbnail = media.source_url;
});
}
});
},
clearPosts() {
this.postsData.posts = [];
this.postsData.totalPosts = null;
},
dispPosts() {
let queryString = 'per_page=' + this.config.postsPerPage +
'&page=' + this.postsData.currentPage;
if (this.postsData.query) {
queryString += '&search=' + this.postsData.query;
}
fetch(this.apiUrl + '/posts?' + queryString)
.then(response => {
if (!this.postsData.totalPosts) {
this.postsData.totalPosts = response.headers.get('X-WP-Total');
}
return response.json();
})
.then(posts => {
posts.forEach((post) => {
this.postsData.posts.push(Object.assign(post, { thumbnail: '' }));
})
return posts;
})
.then(this._setImageUrlsToData);
},
loadNextPage() {
this.postsData.currentPage += 1;
this.dispPosts();
},
searchPosts(query) {
if (!query) {
return;
}
this.postsData.query = query;
this.clearPosts();
this.dispPosts();
},
},
created() {
this.postsData.currentPage += 1;
this.dispPosts();
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment