Vue.js + WordPress

Vue.js + WordPress

From WordCamp Raleigh 2017.

The popularity of JavaScript has lead to an ecosystem that’s vibrant, growing, and to be honest, somewhat out of control. Each day leads to a new framework labeled as the next great thing, but each framework presents it’s own unique set of pros, cons, and frustrations.

In this talk, we will look at Vue.js, one of the most popular JavaScript frameworks available. In 2016, stateofjs.com conducted a survey where over 89% of the surveyed developers gave Vue.js a satisfactory rating, which rates it as the second highest rated framework behind React, which received a rating of 92%. We will look at real world examples of how Vue.js can be integrated into a WordPress project for the front end, the back end, and interaction with the WordPress Rest API.

55ea809c64e7bba42f566d7bdb4e106e?s=128

Allen Moore

April 23, 2017
Tweet

Transcript

  1. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017

  2. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 +

  3. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 + A

    L L E N M O O R E | S E N I O R F R O N T E N D E N G I N E E R
  4. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 W H

    E R E TO F I N D M E
  5. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 W H

    E R E TO F I N D M E @creativeallen https://allenmoore.me https://github.com/allenmoore
  6. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017

  7. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017

  8. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 YES, we're

    hiring!
  9. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 * D

    I S C L A I M E R S
  10. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 This is

    not an official endorsement for Vue.js from 10up.
  11. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 This is

    not an attempt to discredit other MVC Frameworks, such as React or Angular
  12. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 This is

    not a declaration to use Vue.js for every project.
  13. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 JAVAS C

    R I P T F R A M E WO R K FAT I G U E
  14. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017

  15. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017

  16. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017

  17. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017

  18. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017

  19. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017

  20. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017

  21. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017

  22. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017

  23. None
  24. None
  25. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 T H

    E R I G H T TO O L A N D F I T
  26. None
  27. “Just because you have access to jQuery does not mean

    that it should be or has to be used.”
  28. – A L L E N M O O R

    E “Just because you have access to jQuery does not mean that it should be or has to be used.”
  29. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 W H

    AT I S V U E . J S A N D W H Y S H O U L D I C A R E ?
  30. “Vue (pronounced /vjuː/, like view) is a progressive framework for

    building user interfaces. Unlike other monolithic frameworks, Vue is designed from the ground up to be incrementally adoptable.”
  31. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 W H

    Y ?
  32. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 W H

    Y ? • Versatility
  33. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 W H

    Y ? • Versatility • Easy on-boarding
  34. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 W H

    Y ? • Versatility • Easy on-boarding • Vanilla JavaScript
  35. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 W H

    Y ? • Versatility • Easy on-boarding • Vanilla JavaScript • Lack of dependency requirements
  36. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 V U

    E . J S I N T H E WO R D P R E S S A D M I N
  37. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 <div

    id="app"></div>
  38. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 <?php

    2 $defaults = array( 3 'label' => 'Upload an Image', 4 'name' => 'cmm-image-upload', 5 'image_id' => 0, 6 'image_size' => 'thumbnail', 7 'max_uploads' => 50, 8 'type' => 'option', 9 ); 10 11 $args = wp_parse_args( $args, $defaults ); 12 13 $image_src = wp_get_attachment_image_src( $args['image_id'], $args['image_size'] ); 14 $image_src = is_array( $image_src ) ? reset( $image_src ): '';
  39. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 <?php

    2 wp_enqueue_script( 'media-upload' ); 3 wp_enqueue_script( 'cmmis-admin-scripts' ); 4 5 $images = self::getDataType( $args['type'], $args['name'] ); 6 $fieldName = $args['name']; 7 $imageData = self::getImages( $images ); 8 $data = [ 9 'fieldName' => $fieldName, 10 'images' => $imageData, 11 'maxUploads' => $args['max_uploads'], 12 ]; 13 14 wp_localize_script( 15 'cmmis-admin-scripts', 16 'cmmisImageData', 17 $data 18 );
  40. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 import

    Vue from 'vue'; 2 3 4 /** 5 * Instantiate the Vue instance. 6 * 7 * @author Allen Moore 8 * @returns {void} 9 */ 10 new Vue( {el: '#app'} );
  41. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 <template>

    2 </template> 3 4 <script> 5 </script> 6 7 <style> 8 </style>
  42. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 <template>

    2 <div id="app"> 3 <div class="cmmis-images"> 4 <div class="cmmis-image" v-for="image in images" v-bind:data-cmmis-image="image.id"> 5 </div> 6 </div> 7 </div> 8 </template>
  43. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 <div

    class="cmmis-image" v-for="image in images" v-bind:data-cmmis-image="image.id"> 2 <div class="image-item"> 3 <input class="image-id" type="hidden" v-bind:name="field" v-bind:id="field" 4 v-bind:value="image.id"/> 5 <img class="image" v-bind:src="image.src" /> 6 <div class="image-actions"> 7 <a v-bind:href="image.edit" class="cmmis-button -edit"> 8 <svgicon class="svg-edit" icon="edit" width="14" height="14"></svgicon> 9 <span class="screen-reader-text">Edit Image</span> 10 </a> 11 <button class="cmmis-button -delete" aria-pressed="false" v-on:click="deleteImage( image )"> 12 <svgicon class="svg-delete" icon="delete" width="11" height="14"></svgicon> 13 <span class="screen-reader-text">Delete Image</span> 14 </button> 15 </div> 16 </div> 17 <div class="image-caption">{{ image.name }}</div> 18 </div>
  44. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 <div

    class="cmmis-footer"> 2 <button class="button button-primary button-large" aria-pressed="false" v-on:click="openModal"> 3 <svgicon class="svg-plus" icon="plus" width="13" height="13"></svgicon> 4 Add Image 5 </button> 6 </div>
  45. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 /*

    global cmmisImageData */ 2 import './components/icons'; 3 4 export default { 5 6 name: 'app', 7 8 data() { 9 return {}; 10 }, 11 12 methods: {}, 13 14 mounted() {} 15 };
  46. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 data()

    { 2 return { 3 field: `${cmmisImageData.fieldName}[]`, 4 images: [] 5 } 6 }
  47. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 methods:

    { 2 getImages() { 3 const images = cmmisImageData.images; 4 let image; 5 6 for ( let i = 0, len = images.length; i < len; i++ ) { 7 image = images[i]; 8 this.images.push( image ); 9 } 10 } 11 }
  48. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 methods:

    { 2 insertImg( frame ) { 3 const selection = frame.state().get( 'selection' ), 4 length = selection.length, 5 images = selection.models; 6 let imgData = {}, 7 img, 8 imgEditLink, 9 imgId, 10 imgTitle, 11 imgUrl; 12 13 for ( let i = 0; i < length; i++ ) { 14 img = images[i]; 15 imgEditLink = img.changed.editLink; 16 imgId = img.id; 17 imgTitle = img.changed.title; 18 imgUrl = img.changed.sizes.thumbnail.url; 19 imgData = { 20 edit: imgEditLink, 21 id: imgId, 22 name: imgTitle, 23 src: imgUrl 24 }; 25 this.images.push( imgData ); 26 } 27 } 28 }
  49. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 methods:

    { 2 openModal( event ) { 3 const self = this; 4 let frame; 5 6 if ( event ) { 7 event.preventDefault(); 8 } 9 frame = wp.media( { 10 frame: 'post', 11 title: 'Choose an Image', 12 library: { 13 type: 'image' 14 }, 15 multiple: true, 16 button: { 17 text: 'Select Image' 18 } 19 } ); 20 frame.open(); 21 frame.on( 'insert', function() { 22 self.insertImg( frame ); 23 } ); 24 } 25 }
  50. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 methods:

    { 2 deleteImage( img ) { 3 this.images.splice( this.images.indexOf( img ), 1 ); 4 } 5 }
  51. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 mounted()

    { 2 this.getImages(); 3 }
  52. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 import

    Vue from 'vue'; 2 import svgicon from 'vue-svgicon'; 3 import App from './App.vue'; 4 5 Vue.use( svgicon, {tagName: 'svgicon'} ); 6 7 new Vue( { 8 el: '#app', 9 render: h => h( App ) 10 } );
  53. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 V U

    E . J S A N D T H E WO R D P R E S S R E S T A P I
  54. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 <div

    id="app"></div>
  55. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 const

    wpApiUrl = 'https://allenmoore.me/wp-json/wp/v2/posts/?_embed&per_page=5'; 2 3 class DisplayPosts extends Vue { 4 constructor() {} 5 } 6 7 new DisplayPosts();
  56. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 class

    DisplayPosts extends Vue { 2 getPosts( res ) { 3 this.posts = JSON.parse( res.responseText ); 4 5 return this.posts; 6 } 7 }
  57. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 class

    DisplayPosts extends Vue { 2 getData( res, posts = null ) { 3 const self = this; 4 5 res.open( 'GET', wpApiUrl ); 6 res.onload = function() { 7 self.getPosts( res ); 8 }; 9 res.send(); 10 } 11 }
  58. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 class

    DisplayPosts extends Vue { 2 constructor() { 3 const props = { 4 el: '#app', 5 data: {posts: null}, 6 created() { 7 this.fetchPosts(); 8 }, 9 methods: { 10 fetchPosts() { 11 const xhr = new XMLHttpRequest(), 12 self = this; 13 14 this.getData( xhr ); 15 } 16 } 17 }; 18 19 super( props ); 20 this.posts = null; 21 } 22 }
  59. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 <template

    v-for="post in posts"> 2 <article class="entry" role="article"> 3 </article> 4 </template>
  60. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 1 <section

    v-if="post._embedded['wp:featuredmedia'] [0].media_details.sizes['article-thumb']" class="entry-thumbnail"> 2 <a :href="post.link"><img :src="post._embedded['wp:featuredmedia'] [0].media_details.sizes['article-thumb'].source_url" /></a> 3 </section> 4 <header class="entry-header" role="banner"> 5 <h3 class="entry-title" itemprop="headline"><a :href="post.link" rel="bookmark">{{ post.title.rendered }}</a></h3> 6 </header> 7 <section class="entry-content" v-if="post.excerpt.rendered" v- html="post.excerpt.rendered" itemprop="articleBody"></section>
  61. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017 Q &

    A
  62. Allen Moore • @creativeallen • #wcraleigh • allenmoore.me/wcraleigh-2017