How to Use Vue in WordPress (Without Webpack)

If you need a complex front-end feature in WordPress, don't use jQuery. Get a proper library like Vue! We will learn how to set it up in this article.

If you are making a complex front-end feature in WordPress, don’t use jQuery. Get a proper library like Vue!

It will save you lots of time and headache from maintaining it.

In this article, we will learn how to setup Vue in WordPress. This is something that I struggled with because it’s quite different compared to setting it in plain HTML.

What is Vue JS?

Vue JS is a library to create an interactive element. It is the easiest to learn compared to React or Angular.

I won’t teach you the basics of Vue. There are many people covering that already, such as this awesome tutorial from Academind:

Vue Tutorial Playlist by Academind

But those tutorials are in plain HTML. Let’s integrate it with WordPress!


Step 1: Register JavaScript

Minified Vue doesn’t give proper error messages, so during development, you need to use the expanded version.

Here’s how to set the conditional:

add_action( 'wp_enqueue_scripts', 'enqueue_vue' );

function enqueue_vue() {
  if( WP_DEBUG ) {
    wp_register_script( 'vue', 'https://cdn.jsdelivr.net/npm/vue/dist/vue.js', [], '', true );
  } else {
    wp_register_script( 'vue', 'https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js', [], '', true );
  }

  // your app code
  wp_register_script( 'my-app', get_stylesheet_directory_uri()
 . '/js/my-app.js', [], '', true );
}

Then, change the WP_DEBUG constant in your local site’s config to true. Your live site should stay false.

...

define( 'WP_DEBUG', true );

...

Step 2: Enqueue JavaScript

You should only enqueue the script when the page requires it.

For example, we have a Vue app called Cost Calculator that is outputted with [cost-calculator] shortcode.

Here’s how to load the scripts only when the shortcode is used:

add_shortcode( 'cost-calculator', 'shortcode_cost_calculator' );

function shortcode_cost_calculator( $atts ) {
  wp_enqueue_script( 'vue' );
  wp_enqueue_script( 'my-app' );

  // ...
}

Note: If you use the app in all pages, then enqueue it right after you register it in Step 1.

Step 3: Pass in PHP Variables (if needed)

Use localize feature to pass them like shown below:

add_shortcode( 'cost-calculator', 'shortcode_cost_calculator' );

function shortcode_cost_calculator( $atts ) {
  wp_enqueue_script( 'vue' );
  wp_enqueue_script( 'cost-calculator' );

  wp_localize_script( 'cost-calculator', 'ccLocalize', [
    'API_URL' => 'https://wptips.dev/wp-json/wp/v2',
    'items' => [
      [ 'name' => 'Item 1', 'price' => 100 ],
      [ 'name' => 'Item 2', 'price' => 150 ],
    ]
  ] );

  
  return get_template_part( 'shortcode/cost-calculator' );
}

Now your script can use the variable ccLocalize that contains those values.

Step 4: Template and Script

Usually, it’s easier to write the template first.

In this example, we want to list our items with buy button and total cost at the bottom:

<div id="cost-calculator" class="cost-calculator" v-cloak>
  <h1>Cost Calculator</h1>
  <ul>
    <li v-for="i in items" :key="i.name">
      <h3>{{ i.name }}</h3>
      <p>{{ i.price }}</p>
      <a class="button" @click="addToCart( i )">Buy This</a>
    </li>
  </ul>

  <h2>Total Cost: {{ total }}</h2>
</div>

The v-cloak attribute will hide the element before it finished loading. You simply need to add this in your CSS:

[v-cloak] {
  display: none
}

Now for the script, here’s how I write it. Wrapped with self-invoking function, on-ready listener, and no jQuery in sight!

(function() { 'use strict';

document.addEventListener( 'DOMContentLoaded', onReady );
function onReady() {
  initApp();
}

function initApp() {
  new Vue({
    el: '#cost-calculator',
    data: {
      API_URL: ccLocalize.API_URL,
      items: ccLocalize.items,
      total: 0
    },
    methods: {
      addToCart( item ) {
        this.total += item.price
      },
    },
  });
}

})();

Step 5: Need Components?

Let’s say we want to split the items into Component, here’s how I would organize them:

<div id="cost-calculator" class="cost-calculator" v-cloak>
  <h1>Cost Calculator</h1>
  <ul>
    <product-item v-for="i in items" :key="i.name"
      :name="i.name"
      :price="i.price"
      @cart="onAddToCart" />
  </ul>

  <h2>Total Cost: {{ total }}</h2>
</div>

<!-- Template for ProductItem -->
<template id="item-template">
  <li>
    <h3>{{ name }}</h3>
    <p>{{ price }}</p>
    <a class="button" @click="addToCart">Buy This</a>
  </li>
</template>
(function() { 'use strict';

document.addEventListener( 'DOMContentLoaded', onReady );
function onReady() {
  initApp();
}

function initApp() {
  new Vue({
    el: '#cost-calculator',
    // register the component here
    components: {
      ProductItem: ProductItem()
    },
    data: {
      API_URL: ccLocalize.API_URL,
      items: ccLocalize.items,
      total: 0
    },
    methods: {
      onAddToCart( item ) {
        this.total += item.price
      },
    },
  });
}

// <product-item> component
function ProductItem() {
  return {
    template: '#item-template',
    props: [ 'name', 'price' ],
    data: () => { return {} },
    methods: {
      addToCart() {
        this.$emit( 'cart', this.$props );
      },
    }
  };
}

})();

I organize it this way because it’s similar to Webpack format. It will help you transition into it in the future.


Conclusion

This is a quick and dirty way to create Vue app in WordPress. It’s much tidier to use build tools like Webpack, but its barrier of entry can be intimidating.

If you’re wondering how to use Vue with Webpack, check out my other tutorial.

Let me know in the comment if you have any question regarding this topic 🙂

Default image
Henner Setyono
A web developer who mainly build custom theme for WordPress since 2013. Young enough to never had to deal with using Table as layout.
Leave a Reply to VassilisCancel Reply

2 Comments

  1. Hi, I really like your tips and the style of this site! I'm a senior IT but I like coding too so I'm developing with wp and jQuery from 5 years. So I'm just an amateur, but honestly I'm so confident with this library that I'm having hard times to understand why vue or react will change in a better way my job. Since you have explicitly stated don't use jquery but use vue, I would like to understand better how vue would improve my approach with developing webapps or websites. I have searched a lot about it, but I can't clear my mind, especially because after trying to play a bit with react, I had the feeling that with jquery it would take less time.. I understand what are the advantages when switching from LAMP to a MERN system, but I don't understand the advantage of using react or vue instead of jquery on top of a php platform. Maybe you can recommend to me a clear documentation. Many thanks

    • Hi Vassilis, I also thought Vue and React are unnecessary for WP developer. But after learning Gutenberg, I finally understand the benefit.

      The first benefit is a more structured code. If you create an interactive app with jQuery, your code will be all over the place. With Vue or React, they have a standardized way of doing things.

      But for a small feature, like toggling the mobile menu, it's way overkill to use Vue. jQuery or even pure JS will do just fine here.

      I recommend watching the video tutorial I posted in this article. You'll see how powerful Vue is.