Justin Duke

Globally accessible Vue properties

So, Buttondown uses django-js-reverse, which is a fantastic way to handle naming URLs and consolidate routing logic. It means that if I’ve got a bunch of views registered in Django like this…

urls = [
    url(r'^export_data/', miscellany.export, name='export-data'),
    url(r'^resend-confirmation-email', miscellany.resend_confirmation_email, name='resend-confirmation-email'),
    url(r'^confirm-registration/(?P<confirmation_id>.+)', miscellany.confirm_registration, name='confirm-registration'),
    # And so on.
 ]

I can access those in a globally scoped object on the frontend, where keys are the URL names and the values are their corresponding endpoints:

> Urls.export_data()
"/api/emails/export_data/"

This is great for utility methods and such, but Vue’s single file components don’t have access to global variables (or, rather, variables declared on window.) This is for good reason — explicit rather than implicit! — but still means if I want to reference this object in the template code itself:I have to expose it as a computed property:

computed: {
    Urls() { return Urls; }
}

Sure, that’s only three lines, but it’s a pain in the ass feels unnecessarily repetitive. Thankfully, Vue offers a better way, which they refer to as instance properties:

There may be data/utilities you’d like to use in many components, but you don’t want to pollute the global scope. In these cases, you can make them available to each Vue instance by defining them on the prototype.

All you have to do is add Urls (or your object of choice) to Vue’s prototype method:

Vue.config.productionTip = false;
Vue.prototype.Urls = Urls;

// Do the rest of your setup.
new Vue({
  el: '#app',
  router,
  store,
});

And ta-da! All components now have access to Urls, so you can access it like so:

<a :href="Urls.export_data()">Export data</a>

Liked this post? You should subscribe to my newsletter and follow me on Twitter.
© 2017 Justin Duke • All rights reserved • I hope you have a nice day.