75

Can I use lodash _ in all of my vue component?

for example:

I have components organized like below:

App.vue > Parent.vue > Child.vue

I would like all of my component to access _ lodash without defined in every component vm data

===

I am also trying using Mixins. it works. but the result not expected like this _().isEmpty() instead of _.isEmpty()

5
  • 4
    It's a best practice to include any required modules within the component Commented Jun 8, 2016 at 6:06
  • Could you be more concise? Where exactly do you want to use underscore? within your templates or just in your methods / component logic? If you want to reduce redundancy it seems okey to me if you append a stateless library like underscore JS to the global namespace. Commented Jun 8, 2016 at 6:14
  • @Jeff is there any way to reusable it? Commented Jun 8, 2016 at 8:01
  • 1
    @FranzSkuffka I want use underscore in both of component template and logic. Commented Jun 8, 2016 at 8:01
  • 2
    I don't agree. Very common modules like Lodash should be imported globally, so we do not need to write import lodash everywhere. Commented Jan 18, 2018 at 8:47

12 Answers 12

105

Some of the current answers may work in your scenario, but they have downsides:

  • Adding to the window object means your Vue project can't be server rendered, because servers don't have access to the window object.
  • Importing in every file works fine, but it can be a pain if you have to remember to do it in every file.

An alternative approach is to add your library to the Vue prototype. All components inherit from this so they will now all be able to access your library from the this keyword.

import _ from 'lodash';    
Object.defineProperty(Vue.prototype, '$_', { value: _ });

Now lodash is available as an instance method for all components. In a .vue file you can do this without importing anything:

export default {
  created() {
    console.log(this.$_.isEmpty(null));
  }
}

The advantage of using Object.defineProperty rather than a normal property assignment is that you can define a descriptor which allows you to make the property read-only, which it will be by default. This stops consuming components from overwriting it.

This is more thoroughly explained in this blog post (which I wrote).

Note: The downside to this approach is that you get the entire Lodash library, even if you only need one or two functions. If that's a problem, best to use import { reduce, whatever } from "lodash"; at the top of the file requiring it.

Sign up to request clarification or add additional context in comments.

5 Comments

FYI - can write like Vue.prototype.$lodash = lodash
I've added my solution below using the Webpack ProvidePlugin, which I believe is an even cleaner and simpler way of doing things.
I don't like Vue.prototype.$lodash = lodash as much as it can be overwritten. By default, values added using Object.defineProperty() are immutable.
The other more practical downside to this method is that in a non trivial app you will constantly run into issues where the vue instance is not available yet in various hooks and so you are left in the same boat. I think this is best used only for libs you know you will always be accessing from within an area where the Vue instance is instantiated and if it's a general purpose lib used all over then it should go on Window (There are plenty of workarounds for Window access on server side render, it's a non-issue) or be imported individually.
Thanks for the brilliants answer & explanation @anthonygore
33

You could import the lodash into each component:

<script>
  import _ from 'lodash'

  export default {
    methods: {
      test (value) {
        return _.isEmpty(value)
      }
    }
  }
</script>

5 Comments

the example of your code is only wrapping isEmpty method. how about the other lodash methods?
This is just an example based on yours. You could replace the isEmpty with any lodash method.
using import is the right way if you using lodash (_) in child component.
I downvote because we have thousands of vue files, and we don't want to repeat type in import lodash everywhere. That's not good practice.
I installed the lodash globally and did the same. But it's not working for me.
26

For inline templates separated from the js module code it should work with:

  Vue.component('some-tag', {
    computed: {
      _() {
        return _;
      }
    }
  });

And then you can use it in template in "native" way - _.isEmpty(value).

1 Comment

This results in some strange errors in vue3
18
import _ from 'lodash'
Vue.prototype._ = _

Insert these lines in your main.js file and it will work all over your app.

1 Comment

Its not even importing.
12

You could import lodash globally like this

window._ = require('lodash');

Once that has been imported, you will have access to _ from anywhere.

3 Comments

I downvoted because window is undefined when you server render the app.
Also do not forget to add below code into .eslintrc.js file, otherwise ESLint will always whine about _ is undefined. globals: { _: false, },
I upvoted and I think this should be seriously considered because 1) in a nontrivial app you run into all manner of issues where the Vue instance isn't available yet but you need the library 2) few people really need to worry about server rendering, that seems like pedantic objection for no reason.
12

A simple approach that worked for me:

Vue.set(Vue.prototype, '_', _);

This should allow you to use _ in all component templates and vue instances.

2 Comments

this solution just works for one of my projects, not in another one, don't know why... weird.
I like this solution because you can use it in just the component, and not the entire site. As some sites I have worked on use both lodash and underscore, so a global solution wouldn't work in this situation.
5

You can use plugin/mixin like this.

import _ from 'lodash';
exports default {
    install : function(Vue, options){
        Vue.mixin({
            computed : {
                "_" : function(){
                    return _;
                }
            }
        });
    }
}

Comments

3

Bit late to the party but through my research of finding a way to import lodash and other libraries into all my .vue files, I encountered the webpack ProvidePlugin, which achieves everything the OP requested with almost no fuss. To implement this solution, following this fantastic tutorial.

I would note that in the tutorial, he left import "jquery" in his app.js file, which is not required. The plugin with import it automatically.

Comments

1

Check out vue-lodash!! It's a new wrapper for using lodash in vue. You can call it using

Vue._.random(20) // for getting random number between 20

this._.random(20) //or other method you want to use

in any of the component file :)

2 Comments

This works, but do you really need another module in your project to add something that can be added manually with one line?
I think you are making a good point, but it depends on person. Cuz some people might wanna use it often in a big project that contains lots of .vue file, but some might only use it for one .vue component. Just like the idea of having vue-axios. It's not necessary but it's definitely convenient in some cases! :)
1

The proper way is to use provide / inject as such:

import _ from 'lodash';

const app = createApp({
        provide: {
            $_: _,
        }
    });

Then in аnоthег component:

<script>
    export default {
        name: 'аnоthег-component',
        inject: [
            '$_'
        ]
    }
</script>

Comments

0

You can also create a base component and make all of your components extend it.

// base-component
import _ from 'lodash';

export default Vue.extend({
  computed: {
    _() {
      return _;
    },
  },
});
// my-component
import BaseComponent from 'path/to/base-vue';

export default BaseComponent.extend({
  template: '<p>Lodash is available: {{!!_}}</p>'
  methods: {
    doSomehting() {
      // `this._` should be available
    },
  },
});

The pro of this approach is it's not intrusive, so no possible conflict with Vue in the future. Also, you can add even more things to the BaseComponent, like other libraries and external services, and they will be available to all other components.

The con is it's more verbose and you have to remember to inherit from the base component.

Comments

0

For vue users

Go to main.js

import _ from 'lodash'
Vue.set(Vue.prototype, '$_', _)

For nuxt.js users

create main.js inside plugin folder

plugin/main.js

import _ from 'lodash'
Vue.set(Vue.prototype, '$_', _)

Then add into nuxt.config.js

  plugins: ['~plugins/main.js'],

usage are same in both vue and nuxt js

then use in component

this.$_.map(arra,(x)=>{})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.