in JavaScript, Vue.js

Guide: How to use Vue.js with jQuery Plugins

UPDATE

I’m not sure I can recommend that for vue2 anymore. I’m not sure what that solution would be but I would probably go for components now.

The original article is here:

Working with Vue can be awesome. But you might know that it can also give you headaches, when you try to combine it with jQuery plugins or other libraries.

The problem is that jQuery works fundamentally different than Vue. Vue renders everything based of the component’s core data. jQuery is mostly meant to do simple click handling and has powerful abilities manipulate the DOM.

When I looked for help myself I have found some unsatisfying solutions where components did do all the initialization work.
Let me show you how I would combine Vue.js and jQuery.

What’s the goal?

In most cases you can omit using jQuery and find a simple Vue based solution to your problem. Modals, sliders and so on are pretty simple with a Vue component and CSS.

So the goal is to use powerful jQuery plugins that cannot be written quickly in Vue.

We will …

  • … use Vue directives to build a bridge to jQuery.
  • … initialize the plugin when the element is attached.
  • … destroy it when the element is detached.
  • … send events to notify the component.
  • … receive events from the component and pass them to the plugin.

Tutorial Time

I’ve picked Fengyuan Chen’s cropper plugin because it’s a very well written jQuery plugin that you probably cannot rewrite in the next 60 min. using Vue.js alone.
It’s complex and demonstrates how Vue.js can interact with it.

DEMO: https://vue-jquery-cropper-demo.firebaseapp.com/

I’m going to describe how to get that working from the very beginning. Skip the parts you have already done.

Create the project

Congratulations you have a Vue.js project.

Install jQuery and cropper.js

Configure Webpack for jQuery and Vue directives

Add the jQuery source and directives folder to the Webpack alias map.
Normally Webpack would have included the compiled version of jQuery. The recommendation is to have the source included instead.

You can see that the Vue webpack template has added the components folder already. I usually add a bunch of other folders like directives, mixins, etc. For this example we only need to add directives.

This will help us importing dependencies without having to know the exact path. This is also beneficial when you refactor your app along the way. You don’t need to manage relative paths.

Edit build/webpack.base.conf.js and add the highlighted lines.

Don’t forget to add a comma at the end of the components line.

Prepare the App Component

I’m going to start with the component because I believe it’s easier to understand the beauty and simplicity of the component. You can start writing directives later immediately because you then know how to use them in components.

Replace the template in src/App.vue

Replace the script in src/App.vue

A few important things to notice here.

  • We don’t import jQuery nor do we have to deal with its initialization in the component.
  • The Cropper’s options are available as raw data.
  • The Cropper will be initialized when this gets rendered and will be destroyed when the view isn’t visible anymore.
  • The directive’s name will be available in the template as a kebab cased version. MyCropper would become my-cropper.
    To initialize it, we have to add v-my-cropper to an element in the component’s template.

Create the Cropper directive

This is the heart of this tutorial. We’re going to create a Cropper directive that deals with the lower level code DOM manipulation. In this case we’re going to initialize the cropper.

Custom directives provide a mechanism for mapping data changes to arbitrary DOM behavior.
http://vuejs.org/guide/custom-directive.html

Create src/directives/Cropper.js

The very core of every Vue.js directive is a plain object with bind, update and unbind functions.

  • bind: Will be called once the element is attached to the document.
  • update: Called once after bind and every time when the wired data changes. In this case cropOptions is an object. The Vue.js directive needs to know if it is an object. This is why we need to add  deep: true in this case.
  • unbind: Called when the DOM element is about to be removed. We destroy everything here and remove all event listeners.

There will be a couple of changes in Vue 2.
The vm instance is going to be passed as a function argument and won’t be set to this.
The directive’s update function will only be called on update and not initially after bind.

First run

We just did the bare minimum. Let’s see if it works so far.

There is only one quick thing missing. We didn’t add the cropper’s stylesheet yet. Let’s do this and run the app.

Add the first, highlighted line to src/main.js

Start the server.

When everything went fine you should see a photo and a cropbox that you can move around.

cropper-v1

Like it so far? Subscribe to my articles.
[convertkit form=4907393]

Toggle on/off

From here on everything will be pretty easy. We’ll go through it case by case. But each will be almost too simple.

Let’s enabled and disable the cropper with a button. Think of switching from page to page or opening the cropper after a user has selected a file. That proves that the cropper can be initialized at any time.

Edit the script in src/App.vue

  • add showCropper: false to data.
  • add a method to toggle showCropper .

Edit the template in src/App.vue

  • Add a button with a @click handler.
  • Add a v-if directive to the img  tag.

Every time the image shows up your custom cropper directive’s bind and update functions will be called.

When showCropper is set to false the cropper’s unbind function will be called.

There isn’t much we can mess up from here on.
The cropper will be loaded when it is needed and unloaded after the user is done.

Changing options

We already have everything it takes to update the cropper’s options. If we had a plugin that would accept new options on existing jQuery instances then we wouldn’t have to create destroy and recreate the plugin. Unfortunately the cropper doesn’t allow this.

Let’s add a switch that changes whether or not the image is zoomable.

Edit the template in src/App.vue

Easy, right?

Getting data out of the directive

The cropper has a crop callback function. We’re going to emit an event whenever that callback will be called.

Edit src/directives/Cropper.js

Edit the App component’s script to handle crop events.

Edit the App component’s template to show the crop data.

As you’ve seen I have chosen to emit events from the directive and listen to them in the app component. Ask yourself why I choose to do that. I also could have chosen to create a method in the app component and use that to bind it to the cropper’s crop listener.

Anti-pattern options.crop = this.vm.handleCrop

Evoking actions from outside

This final change shows how events can flow from a component to a directive. We’re going to use that to call cropper’s actions. Let me show you how I would add a rotate button.

Edit the App component’s template and add the rotate button.

Edit src/directives/Cropper.js to add and remove the event listener.

Summary

Et voilà you’re done!

The beauty of this setup is that the directive is decoupled from the components and can be used multiple times per component. It will be initialized automatically right after the element has been attached to the DOM and will be destroyed before it gets removed.

I hope you have enjoyed that article. Feel free to message me or post something to the comments section if you have questions for suggestions.

Best,
Christian