In my last two articles, I covered the basics of the JavaScript framework VueJS and how to use it with the WordPress REST API. I discussed using the basics of VueJS and templating, as well as how to use components to make sections of the app reusable and modular. In this post, I will show you how to use the vue-router to move between states that use these components.
VueJS is not strongly tied to the official router, and the official documentation even provides alternatives to it. That said, the vue-router, is very simple and clean, so let’s build a router with three states: home, posts, and post.
Getting Started
In my last article in this series, I created a simple theme using VueJS, which you can find on Github. The reason for using a theme was to leverage WordPress’ routing. But not that we don’t need that, this code can move out of a WordPress theme if you want.
I’ll be sticking to index.php of that theme for simplicity, but that’s no longer really needed. The one important change I did was add the vue-router component to the scripts being enqueued by functions.php:
<?php add_action( 'wp_enqueue_scripts', function () { wp_enqueue_script( 'jquery' ); wp_enqueue_script( 'vue-router', get_template_directory_uri() . '/assets/js/vue-router.js', [ 'vuejs' ] ); wp_enqueue_script( 'vuejs', get_template_directory_uri() . '/assets/js/vue.js' ); } );
Also, we are going to need two components, one for creating a list of posts and one for showing one post. Here are those two components, borrowed from the last article:
var posts = Vue.component('post-list', { template: '#post-list-tmpl', data: function() { return{ posts: [] } }, mounted: function () { this.getPosts(); }, methods: { getPosts: function () { var self = this; $.get( config.api.posts, function( r ){ self.$set( self, 'posts', r ); }); }, } }); var post = Vue.component( 'post', { template: '#post-tmpl', data: function() { return{ post: [] } }, mounted: function () { this.getPost(); }, methods: { getPost: function(){ var self = this; $.get( config.api.posts + 42, function(r){ r.title = r.title.rendered; r.content = r.content.rendered; self.$set( self, 'post', r ); }); } } });
The “post” component is hard-coded to post ID 42 for now. Later on, that ID will become dynamic– provided by the router to set the current ID.
Using The Vue-Router
Before we work on our components, I want to introduce the router and navigation using routes with hard-coded templates, so you can see how it works.
We use the function Vue Router to construct a router instance and provide an array of options and routes. The routes can be inline components, which we will start with, or components defined already in the app, which we will use later.
Let’s start with inline components, that just have a template argument:
var router = new VueRouter({ mode: 'history', routes: [ { path: '/', template: '<div>Hi</div>' }, { path: '/hi/roy',template: '<div>Hi Roy</div>'}, { path: '/hi/shawn', template: '<div>Hi Shawb</div>' }, ] }); new Vue({ router, }).$mount('#app')
The HTML for this little app will need to make use of the “router-link” directive that will be transformed into links that create state transitions:
<div id="app"> <p>Current route name: {{ $route.name }}</p> <p> <router-link to="/">Home</router-link> <router-link to="/hi/roy">Say Hi To Roy</router-link> <router-link to="/hi/shawn">Say Hi To Shawn</router-link> </p> <router-view></router-view> </div>
If you run this, you should see the three links moving between states. In addition, the browser’s address should update to the different URL routes.
Now let’s start again using our posts and post components. Our new router will have three routes: home, posts, and post. The third one “post” will need to use a dynamic URL component to represent post ID. In the route path argument we will use “post/:id” and in the component, we can access the value for ID with this.$route.params.id so we can update our API call to get the right ID:
var post = Vue.component( 'post', { template: '#post-tmpl', data: function() { return{ post: [] } }, mounted: function () { this.getPost(); }, methods: { getPost: function(){ var self = this; $.get( config.api.posts + self.$route.params.id, function(r){ r.title = r.title.rendered; r.content = r.content.rendered; self.$set( self, 'post', r ); }); } } });
With that component updated, we can use it and the posts component to make the router:
var router = new VueRouter({ mode: 'history', routes: [ { path: '/', name: 'home', template: '<div>Hi Roy.</div>' }, { path: '/posts', name: 'posts', component: posts }, { path: '/posts/:id', name: 'post', component: post }, ] }); new Vue({ router, }).$mount('#app')
Of course, we will need to update our HTML and make sure we have templates for both components. This HTML should be familiar by now:
<div id="app"> <p> <router-link to="/">Home</router-link> <router-link to="/posts">Posts</router-link> </p> <router-view></router-view> </div> <script type="text/html" id="post-list-tmpl"> <div id="posts"> <div v-for="post in posts"> <article v-bind:id="'post-' + post.id"> <header> <h2 class="post-title"> {{post.title.rendered}} </h2> </header> <div class="entry-content" v-html="post.excerpt.rendered"></div> <router-link :to="{ name: 'post', params: { id: post.id }}"> Read More </router-link> </article> </div> </div> </script> <script type="text/html" id="post-tmpl"> <div class="post"> <article v-bind:id="'post-' + post.id"> <header> <h2 class="post-title"> {{post.title}} </h2> </header> <div class="entry-content" v-html="post.content"></div> </article> </div> </script>
Going Further
In this post, you have learned how to create a router using VueJS and link views to existing components. I encourage you to explore the VueJS router documentation and learn more. Good next steps would be to add paginated routes, routes for terms and switch from using post ID to post slug in the post route.
Beyond that, we have now covered all the basics of using the WordPress REST API with VueJS. I even provided a theme that you can expand on to create something really cool, I know I’m going to. Be sure to share what you create.
To learn more about the REST API JavaScript frameworks, check out Caldera Learn.
3 Comments