DEV Community

Lisa Armstrong
Lisa Armstrong

Posted on • Updated on

Using Vue in WordPress

Like peanut butter and jam sometimes two good things are even better together.

In this tutorial I'll show you how to use Vue in a WordPress site. The tutorial is meant for those who have coded in WordPress and Vue or is interested in either one. Knowledge in PHP, WordPress, Javascript, Vue will help.

Vue Programmers: Why WordPress?

Statistically, WordPress runs about a third of the world's websites. If you've created something in Vue you'd like to share, WordPress is a good platform to make it available on.

You can customize your own site, or share your code on WordPress' plugin repository.

WordPress Programmers: Why Vue?

The short answer is, Vue is known for its simplicity and robustness making it a solid choice for development. If you're adding functionality to your site, it makes a good tool to get up and running with. It's in JavaScript, so it's familiar to most developers.

WordPress uses React, can I even use Vue?
Of course! Although some features in WordPress may be in React, you are not limited to it.

WordPress is open source, do what makes you happy.

Tutorial Overview

We'll make a short code that displays something generated in Vue. We'll be using a simple example because this is more about how to put Vue and WordPress together rather than what they do.

The approach is:

  1. Create a plugin in WordPress to use the code
  2. Create a shortcode in the plugin
  3. Create your Vue code
  4. Load Vue, then your code file.
  5. Make sure your .js file is loaded after the dom is drawn.

That's basically it. Let's get into the details.

WordPress: The Plugin.

Plugins are both simple and robust, they allow you to add functionality to your site. This plugin will be a simple 'hello world' type. We'll call it 'wp-vue-tutorial', so let's begin:

1) Create a new folder in your WordPress plugin directory.

This is where the files will be kept, it should be the name of the plugin. For this tutorial let's use:
/wp-content/plugins/wp-vue-tutorial

We need a 'master file', so let's make that.

2) In the directory, create a master file with the plugin name.

This file called 'wp-vue-tutorial.php' so it should look like:
/wp-content/plugins/wp-vue-tutorial/wp-vue-tutorial.php

Yes, the plugin name, folder name and master file name are all the same so WordPress knows where to find it.

Once WordPress opens it up, it needs some more info on what this thing is. That's included in the Header. We're keeping it simple, so in wp-vue-tutorial.php, add the following code:

<?php
/**
 * Plugin Name: WordPress Vue Tutorial
 * Description: A demo on how to use Vue in WordPress.
 */
?>

More info: https://developer.wordpress.org/plugins/

If you go to your WordPress Dashboard, you'll see your plugin.
Dashboard -> Plugins
It should appear in the list.

3) Activate your plugin.

Click Activate on your plugin.

Now it's loaded, but not much happens because there's no code to run. So, let's create a shortcode.

A shortcode tells WordPress to insert the content generated by your PHP code into the content of the page or post.
Ex. The user enters something like [myshortcode] and when the page is displayed, it shows 'This is content from my shortcode.'

Note: WordPress' current text editor (Gutenberg) allows you to put in blocks of content in. A shortcode will still work with that, in fact there is a block specifically for short codes. We're using shortcodes in this tutorial because it's a standard that works.

For more info: https://codex.wordpress.org/Shortcode_API

4) Create a shortcode in your Plugin.

Add the following code to your plugin file (wp-vue-tutorial.php):

 //Add shortscode
 function func_wp_vue(){
   return "Hello Shortcode";
}
add_shortcode( 'wpvue', 'func_wp_vue' );

Breaking it down:
The function func_wp_vue() returns the text Hello Shortcode.

add_shortcode( Make this shortcode available.
'wpvue', The code the user uses in the content
[ 'wpvue'].
'func_wp_vue' The function returning the string to display.
); End of shortcode.

Your file should look like:

<?php
/**
 * Plugin Name: WordPress Vue Tutorial
 * Description: A demo on how to use Vue in WordPress.
 */

//Add shortscode
 function func_wp_vue(){
 return "Hello Shortcode";
}
add_shortcode( 'wpvue', 'func_wp_vue' );
?>

Test it.
Edit, or add a new WordPress page. In the content area, type in [wpvue].
Publish the page and have a look at it. You should see Hello Shortcode.

The short code can return more than a word, we can put in an element in the too.

Let's change the code to:

//Add shortscode
function func_wp_vue(){
  $str= "<div id='divWpVue'>"
    ."Message from Vue: "
    ."</div>";
  return $str;
} // end function

Test it again.

Set Up Vue

To use Vue, you need three things:

  1. Vue js files need to be loaded on the page so you can use the framework.
  2. You need an element on your page Vue can work in. Usually a div.
  3. You need your Vue code in a .js file to do its work in the element.

Load Vue.js

Let's start with adding Vue. You can add Vue through a link to a CDN. There's 2 versions, one for development with debugging options and one for production that is faster and leaner.
We'll use the development one: https://cdn.jsdelivr.net/npm/vue/dist/vue.js

We need to load this into WordPress, which can be done through the magic of 'wp enqueue scripts' and 'wp_register_script'.
This hook automatically load the script into WordPress' head when needed.

It looks like:

function func_load_vuescripts() {
 wp_register_script( 'wpvue_vuejs', 'https://cdn.jsdelivr.net/npm/vue/dist/vue.js');
}
add_action('wp_enqueue_scripts', 'func_load_vuescripts');

Break down:

function func_load_vuescripts() { Define the function .
wp_register_script( Tell WP this script exists
(we'll load it later) .
'wpvue_vuejs', This is the WordPress reference to the script.
''https://cdn.jsdelivr.net/npm/vue/dist/vue.js'', Actual script file.
); Close the wp_register_script.
} Close the function.
add_action( WordPress, do this.
'wp_enqueue_scripts', Hook into 'wp_enqueue_scripts'.
'func_load_vuescripts' Do this function for 'wp_enqueue_scripts' .
); End action .

For more info:

We'll add the code to your plugin file, above the shortcode.
It should look like this:

<?php
/**
 * Plugin Name: WordPress Vue Tutorial
 * Description: A demo on how to use Vue in WordPress.
 */

//Register Scripts to use 
function func_load_vuescripts() {
 wp_register_script( 'wpvue_vuejs', 'https://cdn.jsdelivr.net/npm/vue/dist/vue.js');
}
add_action('wp_enqueue_scripts', 'func_load_vuescripts');

//Add shortscode
function func_wp_vue(){
  //Build String
  $str= "<div id='divWpVue'>"
  ."Vue code here: "
  ."</div>";

  //Return
  return $str;
} // end function

//Add shortcode to WordPress
add_shortcode( 'wpvue', 'func_wp_vue' );
?>

Right now, we told WordPress about Vue.js, but we haven't loaded it. You load it in the shortcode function so it fires when the shortcode is running. Makes sense?

Include the following in your shortcode function:

//Add Vue.js
  wp_enqueue_script('wpvue_vuejs');

Breakdown:

wp_enqueue_script( WordPress, load this script
'wpvue_vuejs' It's called 'wpvue_vuejs' defined when we registered the script.
); End enqueue script

It should look like:

function func_wp_vue(){
  //Add Vue.js
  wp_enqueue_script('wpvue_vuejs');
  
  //Build String
  $str= "<div id='divWpVue'>"
  ."Vue code here: "
  ."</div>";

  //Return
  return $str;
} // end function

Now if you run it, not much has changed, but if you were to look in the source code of the page you'd find :

<script type='text/javascript' src='https://cdn.jsdelivr.net/npm/vue/dist/vue.js?ver=5.1.1'></script>

Vue is now loaded, we can use the div generated in the shortcode ('divWpVue'), all we need is some Vue code to run in that div.

Create Your Code File for Vue

Make a new file: vuecode.js your plugin directory:
wp-content/plugins/wp-vue-tutorial

You should have 2 files in there:

  • wp-vue-tutorial.php
  • vuecode.js

More Info:
https://vuejs.org/v2/guide/

This is a really simple demo, so include the following code:

var app = new Vue({
  el: '#divWpVue',
  data: {
    message: 'Hello Vue!'
  }
})

Breakdown:

var app = new Vue({ We're creating a var called 'app' that is actually a Vue instance.
el: '#divWpVue', This app runs in the element 'divWpVue'.
data: { This app has data with it.
message: 'Hello Vue!' One piece of data is called 'message' and has the value 'Hello Vue!'
}
})
Close the data section
Close the app section

For more info on Vue:

In order to display the message, you need to include the data message in the div. Change your shortcode function (func_wp_vue) to include {{message}}.

The double curly brackets is a way of including Vue stuff in your HTML file. If you add {{message}} inside the element you've assigned to your Vue instance, it will magically appear. This is the short non-technical answer of course.

Important! If you check your file, and everything is working, you will see 'Hello Vue!' where {{message}} was placed. If you see {{message}}, something's not working.

Let's add the {{message}} to the shortcode.

function func_wp_vue(){
  //Add Vue.js
  wp_enqueue_script('wpvue_vuejs');
  
  //Build String
  $str= "<div id='divWpVue'>"
  ."Message from Vue: {{ message }}"
  ."</div>";

  //Return
  return $str;
} // end function

If you test it now, it won't work, {{message}} will display, not 'Hello Vue!'

Why? Because we haven't loaded your vuecode.js file yet. We can load it the same was as the Vue CDN file, right?

Hmm... not exactly. You're on the right track, but there's a couple of Gotcha's to watch out for. Let's walk through it.

To register vuecode.js, you would expect something like the following would work:

 wp_register_script('my_vuecode', 'vuecode.js')

No, it won't because WordPress can't find vuecode.js.

Gotcha: Your file isn't loading

Remember the shortcode is displayed on a page with a different path than the plugin. It's a kind of logistical hall of mirrors, nothing is where it appears.

To fix it, you need to be more precise about where the file is located. That's handled by adding a WordPress function that returns the path of the plugin file you're using. plugin_dir_url will do the trick.

wp_register_script('my_vuecode', plugin_dir_url( __FILE__ ).'vuecode.js') 

More info on plugin urls: https://codex.wordpress.org/Function_Reference/plugins_url

Gotcha: Vue.js needs to load first

Your vuecode.js runs on Vue, so make sure those files are loaded before you start running your Vue code.

To ensure that, tell WordPress it depends on Vuejs by adding the dependency to the register_script function. Use the handle from the Vue.js script register.

wp_register_script('my_vuecode', plugin_dir_url( __FILE__ ).'vuecode.js', 'wpvue_vuejs' );

GOTCHA: Your file with Vue code has to come AFTER the DOM loads

Why? It loads scripts in the head, but your vuecode.js controlling a div in the body and it hasn't been loaded yet. It can't find it and throws an error.

So, load Vue.js first, then the body with the DOM, then the controlling script ( vuecode.js ). You can do that through the register script by adding a 'true' value to the parameters. 'true' tells WordPress to load the script in the footer.

It should look like this:

wp_register_script('my_vuecode', plugin_dir_url( __FILE__ ).'vuecode.js', 'wpvue_vuejs', true );

Breaking it down:

wp_register_script( WordPress, register this script.
'my_vuecode', Its handle (reference) .
plugin_dir_url( __FILE __).'vuecode.js', The file is located in the same directory as this plugin. This is the link to it.
'wpvue_vuejs', Make sure this is loaded first. It's a reference to another registered script.
true Load the script in the footer.
); Close the function.

Your function to load the scripts should look like:

//Register scripts to use
function func_load_vuescripts() {
    wp_register_script('wpvue_vuejs', 'https://cdn.jsdelivr.net/npm/vue/dist/vue.js');
    wp_register_script('my_vuecode', plugin_dir_url( __FILE__ ).'vuecode.js', 'wpvue_vuejs', true );
}
add_action('wp_enqueue_scripts', 'func_load_vuescripts');

More Info on Registering Scripts:

That should do it. But, you still won't see anything, why not?
After all that, you've only registered the script. WordPress knows all about it, but you haven't told it to fire it.

Gotcha: Don't forget to enqueue /load the script

Ok, this one is just like enqueing the Vue.js script. Add the following to the shortcode function -- 'func_wp_vue'.

wp_enqueue_script('my_vuecode');

'func_wp_vue ' should look like:

//Return string for shortcode
function func_wp_vue(){
  //Add Vue.js
  wp_enqueue_script('wpvue_vuejs');
  //Add my code to it
  wp_enqueue_script('my_vuecode');

  //Build String
  $str= "<div id='divWpVue'>"
    ."Message from Vue: {{ message }}"
    ."</div>";

  //Return to display
  return $str;
} // end function

//Add shortcode to WordPress
add_shortcode( 'wpvue', 'func_wp_vue' );

Putting It All Together:

You should have your plugin called 'wp-vue-tutorial'. In the plugin directory, there should be 2 files:

  • vuecode.js (that has the Vue code in it)
  • wp-vue-tutorial.php (with the WordPress code)

vuecode.js

Your Javascript file that runs off of Vue.js should look like the following:

var app = new Vue({
  el: '#divWpVue',
  data: {
    message: 'Hello Vue!'
  }
})

wp-vue-tutorial.php

Your WordPress file that defines the plugin and has the shortcode code in it should look like:

<?php
/**
 * Plugin Name: WordPress Vue Tutorial
 * Description: A demo on how to use Vue in WordPress.
 */

//Register scripts to use
function func_load_vuescripts() {
    wp_register_script('wpvue_vuejs', 'https://cdn.jsdelivr.net/npm/vue/dist/vue.js');
    wp_register_script('my_vuecode', plugin_dir_url( __FILE__ ).'vuecode.js', 'wpvue_vuejs', true );
}
//Tell WordPress to register the scripts 
add_action('wp_enqueue_scripts', 'func_load_vuescripts');


//Return string for shortcode
function func_wp_vue(){
  //Add Vue.js
  wp_enqueue_script('wpvue_vuejs');
  //Add my code to it
  wp_enqueue_script('my_vuecode');

  //Build String
  $str= "<div id='divWpVue'>"
    ."Message from Vue: {{ message }}"
    ."</div>";

  //Return to display
  return $str;
} // end function

//Add shortcode to WordPress
add_shortcode( 'wpvue', 'func_wp_vue' );
?>

Note: You can include the shortcode in a theme's functions.php file, it will still work the same as long as the the theme is being used, or its functions.php file isn't over-written with an upgrade.
I prefer the plugin because it separates out the style from the content and usually my Vue code is about content anyway.

More Info:
https://codex.wordpress.org/Functions_File_Explained

If you use the theme functions file, you need to call the file path in relation to your theme, not the plugin.

More Info:
https://codex.wordpress.org/Function_Reference/get_template_directory

Download Files

You can download the files at:
https://github.com/workingwebsites/wp-vue-tutorial

Conclusion

Ok, so 'Hello Vue' doesn't exactly set the world on fire. However, once you've got that in there, you can see how you can add a lot of functionality to your WordPress site through Vue.

By using Vue in your WordPress site, accessing API's and making your site more interactive gets easier. Likewise, if you have some crafty code written with Vue, dropping it into a WordPress site (and there's lots of them) is not a big trick.

Like peanut butter and jam, combining two good things make it better!

Top comments (40)

Collapse
 
shamsail profile image
shamsail

Hi Lisa,
I need an help regarding this enqueue problem.
I have 3 folders in my dist folder after build vue app. 1)js 2)css 3)img . I have successfully enqueued the scripts and styles in my wordpress plugin by using wp_enqueue_script & wp_enqueue_style.
The problem that I'm facing is that I am not able to add/enqueue the 3 folder of img in which I have my image assets that are being used for plugin.
Let's make it simple, generate a default simple vue app and run in wordpress. After enqueue, it'll give js and css but it'll not show the vue image(logo) .

Collapse
 
workingwebsites profile image
Lisa Armstrong

I assume you're setting this up as a plugin. If so, you can reference your images through the plugin url.
developer.wordpress.org/reference/...
That will give you the path to images.
Hope this helps.

Collapse
 
shamsail profile image
shamsail • Edited

Hi,
Thanks for your reply. I have tried this already and it didn't work for me. Also, I had tried by changing paths and folders but nothing seems to work in case of images.

These line of codes are working perfectly with js and css of vue app.

wp_register_script('wpvue_vuejs', plugin_dir_url( FILE ).'dist/js/app.js', [], '1.0.0', true);
wp_register_script('wpvue_vuejs1', plugin_dir_url( FILE ).'dist/js/chunk-vendors.js', true);

wp_enqueue_script('wpvue_vuejs');
wp_enqueue_script('wpvue_vuejs1');
wp_enqueue_style('wpvue_css1', plugin_dir_url( FILE ).'dist/css/app.css', true);

I tried for image source like this but it's not working at all.
plugins_url( 'dist/img/logo.png', dirname(FILE) );
plugins_url( 'dist/img/logo.png', (FILE) );

FILE

Thread Thread
 
workingwebsites profile image
Lisa Armstrong

The issue could be where your /img/logo.png file is in Vue.

As I understand it, the dist folder is a compilation of .js, .css files compiled by Webpack .
Webpack ignores image files and won't compile or put them in the /dist/ folder.

Bottom Line: Your image folder may not be landing in the WP plugin file.

The way around that is a 'public' folder.
see: cli.vuejs.org/guide/html-and-stati...

Try putting your image folder under the public folder (/public/img/logo.png) and tinker around with the path until it works.
To test, compile, upload to WP and check the plugin directory to see if the file is there.
If it's there, but not showing up -- that means it's uploaded, you just need to adjust the path to it.

Hopefully that gets you going the right direction.

Collapse
 
noelmc3 profile image
NOTB

Hi Lisa,
Your article is exactly what I was hoping to find on the internet, thank you so much for this.

Now I have a question.. How do I print WordPress/PHP values using vue js.

For example, in a blog page, I may use Vue to generate the HTML template & the interaction aspects.. but I would like the actual values in the template to be WordPress values such as the_title(); the_excerpt (); and so on..

How do I accomplish this?

Collapse
 
workingwebsites profile image
Lisa Armstrong • Edited

Good question!

I think your best approach would be to set up a component, and pass the the_title(); etc. in as a prop (variable).

See: vuejs.org/v2/guide/components.html
This will guide you through making a component.

Passing props (variables into your components):
vuejs.org/v2/guide/components.html...

In the end, you'd end up with something like..
in vuecode.js

Vue.component('wp-vue-title', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})
Enter fullscreen mode Exit fullscreen mode

In your template:

<wp-vue-title title="<?php the_title(); ?> "></wp-vue-title>
Enter fullscreen mode Exit fullscreen mode

Note: In the example tutorial, it adds a shortcode.

In your case, you probably wouldn't need it, since it sounds like you're doing this through the template. Shortcodes work better on the text side.

Good luck!

Collapse
 
rockykev profile image
Rocky Kev

Hey Lisa - thanks for this post! Got it up and running immediately by the end of the tutorial. Thank you!

One suggestion, and this is totally opinionated, so you can take it with a grain of salt - cleaner naming of functions/scripts/variables. There's a bit of redundancy, and I do believe in naming things after their actions. Again, just my opinion.

Collapse
 
chrisjimallen profile image
Chris Allen

This is a fantastic guide. I've built several VueJS apps using the Nuxt framework, but I had a requirement to embed some Vue into a WordPress page. Compiled NuxtJS apps do not play well with WordPress, but this is ideal. Great idea to package it as a plugin.

Collapse
 
dgmann profile image
DGMANN • Edited

Hey Lisa!
Thank you for your great inspirational article. I extended it a little bit: dev.to/paloma/vue-application-as-a...

Thank you, Paul!

Collapse
 
shomalikhashayar profile image
Khashayar Shomali • Edited

Hi Lisa, I write a headless WordPress theme with Quasar framework(Vuejs) and when I build the app the images are not load, but load correctly on localhost (quasar dev), Why?

Thanks for your help.

On XAMPP and real host:
image

On Quasar localhost:
image

Collapse
 
ariesalma1 profile image
Arie

What would be the implication of simply putting the CDN link in the header file , then just use it wherever I want? Honestly after years w WP, trying bypassing all the registering code etc never caused me problems.

Collapse
 
workingwebsites profile image
Lisa Armstrong

You're right, technically you don't have to register them, but it is a recommended practice to manage scripts and dependencies.

From WordPress:
"the main purpose of the register functions is to allow you to simplify your code by removing the need to duplicate code if you enqueue the same script or style in more than one section of code."

If you were using your Vue plugin in a number of areas, it would be handy. It would make the plugin more standalone, and not dependent on a line of code in the header.

Collapse
 
lopher profile image
lopher

Hello excellent article, just what I was looking for, a question if you can enlighten me, how should I do so that when changing pages I do not reload the navigation screen.

Best regards from Argentina,Hernán lopez Ocampo

Collapse
 
workingwebsites profile image
Lisa Armstrong

I'm glad you found the article helpful!

I'm not sure what you mean by not reloading the menu bar.

Do you want to change the content of the page, but not the menu bar etc.?

If so, you would probably use WordPress's REST API to get the content through Vue, and change it that way.

The trick is how to navigate from one page to another.

There are tutorials out there that may help. Try searching for 'wordpress, headless api, vue'. That may help.

Collapse
 
abrahambrookes profile image
Abraham Brookes

Great walkthrough. What if I want to compile my Vue app using webpack? In the article you say that we need to load the vue library before the DOM loads, and then our vue app after the DOM has loaded. This would mean that we can't bundle vue together with our app code, is that right?

I'm fiddling with it and my vue bundled code is loading, but it's not mounting onto my #app element...

Collapse
 
workingwebsites profile image
Lisa Armstrong • Edited

The key is to make sure everything is loaded so it can work.

That means:

  1. Vue is loaded so your app will work.

  2. The Dom element is loaded so your app can attach to it

  3. The app is loaded so it works.

Generally in Wordpress, scripts are loaded in the head, before the Dom.

This is ok for loading Vue, because it doesn't need the Dom.

However, the app should be loaded after the Dom, so it's best to put it in the footer.

That means if you are loading the two together as one package, put that in the footer since it needs the Dom.

Does that make sense?

Collapse
 
abrahambrookes profile image
Abraham Brookes

Yep makes sense, turns out it was my webpack config, I opted to use laravel mix instead and problem solved! Thanks for the article.

Collapse
 
abrahambrookes profile image
Abraham Brookes • Edited

What about using images from your plugins directory? When using <img :src="require(path/to/image)" />, the image is moved to an 'images' folder in the plugins' root directory, but the image path is compiled to /images/image.png, which, when loaded in the wordpress plugin translates to the absolute URL www.domain.com/images/image.png - and that's incompatible with the wordpress folder structure.

I can use an absolute URL that accesses my plugins folder from the site root (ie: <img src="/wp-content/plugins/my-plugin/images/image.png" />) but I would prefer not to do that because this component needs to work with different environments and potentially different plugin names, I don't want to shackle it to one path.

I'm probably going to write a little filepath utility in here somewhere, but maybe you already have a solution for using images in your vue-wordpress plugin?

Collapse
 
workingwebsites profile image
Lisa Armstrong

For that, use the plugin_dir_url().
codex.wordpress.org/Function_Refer...

The code would be something like:
plugin_dir_url( __FILE__ ) . 'images/foo-picture.jpg';

This means the plug-in can be anywhere on the site, but it will still find the 'images' directory in your plug-in folder.

Note: This is a PHP function, so if you're including it in JavaScript (Vue), allow for that.

Ex. <img :src="<?php echo plugin_dir_url( __FILE__ ) . 'images/foo-picture.jpg'; ?>" />