2

i have a system in which i have to set up some reusable functions to be used all over my application, now i have created a vue mixin in my main main.js file now when i call that function from vue components it works just fine but when i try to call the same function inside a js file i get an error of undefined here's my code

main.js

Vue.mixin({

   methods: {
        test: function () {
            return 1;
        },
   }
});

Vue Components

//this works
    async created() {
        alert(this.test());
    }

services.js

import { API } from 'aws-amplify';
import { Auth } from "aws-amplify";

import axios from 'axios'

export default {
somefunction(){
//this doesnot work
 alert(this.test());
}
}

can someone tell me how can i use vue mixins in regular js files, i looked on the internet but couldn't find anything related to this

uneeb meer
  • 882
  • 1
  • 8
  • 21

3 Answers3

4
// mixin.js

export myMixin = { computed: { foo(): 'hi' } }

Simply create an object (and likely mark it as an export) besides adding it to vue.

It's just an object. It has special names like computed, data etc. in it, but it's just an object.

// usage.vue

import { myMixin } from './path/to/myMixin.js'
console.log( myMixin.computed.foo ) // hi

export default {
  mixins: [ myMixin ],
  computed: { bar(): { this.foo } // hi
}

In the above example, I'm not using a global mixin, because, to quote vue docs

Use global mixins sparsely and carefully, because it affects every single Vue instance created, including third party components.

Now, if you really need a global mixin, that's why it's for, but note that to use myMixin outside of vue export default, you'd need to access it via global scope, like window, or import it like above. For more info refer to queries like these: global functions in js.


My preference:

// in a file at /path/to/index.js
export { myMixin1 } from './myMixin1' // ...

// usage.vue
import { myMixin1, myMixin2 } from './path/to'
export default { mixins: [ ... ] }

or alternatively where needed, (because mixins can include other mixins ;) though I find it harder to use them in other JS then

export myMixin1 = { ... }
export myMixin2 = {
  mixins: [ myMixin1 ]
  // ...
}

// usage.vue
import { myMixin2 } from 'path/to/myMixins'
export default {
  mixins: [ myMixin2 ] // contains both 1 and 2
}

Note you can also declare in Vue files (single file components), and then import from them just as they were Javascript.

Also, you (obviously) don't need to export them - they're already useful for separating concerns.

// example.vue
<script>
  export myMixin = { ... }

  // all mixins can interact with each other
  // because in the end, they will be parts of the same object
  myToggle = { ... }
  mySuperComplicatedBit = { ... }
  // so B can call this.A

  export default {
    mixins: [
      myMixin,
      myToggle,
      mySuperComplicatedBit
    ],
    ...
  }
</script>
<template> ...

// other.vue or other.js
import { myMixin } from 'path/to/example.vue'

Cheers and good luck

tony19
  • 125,647
  • 18
  • 229
  • 307
n-smits
  • 685
  • 7
  • 20
0

If your mixin is generic you could use a global mixin and access it via the main application. But I don‘t really see the point, then why have a mixin in the first place?

main.js

export default new Vue({
    mixins: [YourMixin]
    ...
})

somecode.js

import vue from ‚./main.js‘

vue.method()

Edit: suggestion

To be honest, I‘d rather turn your implementation around and have a service expose a functionality, which is then integrated to the Vue components via a mixin.

János Veres
  • 187
  • 1
  • 7
  • The reasons I'd want it in a mixin even if global is to separate concerns. (Though I don't do global mixins.) It's simpler to think about the problem when my methods and computeds aren't tripping over one another. The problem is ampified by vue approach of separating by type (methods, data...) and not concern (my modal, my computation). – n-smits Jun 11 '20 at 19:26
  • I get that, although in Mixins you tend extend the vue component, such as defining new properties as well. I would think a mixin would break if you have a computed property which is referencing for example this.$store and use that property outside the context of a vue component, don’t you agree? – János Veres Jun 12 '20 at 07:23
  • True -- So dont. Instead: A = generic funcs, B = vuex funcs, C = A + B. Seems reasonable, no? Besides, always marginalize the framework / plugin (see the full argument here https://youtu.be/2dKZ-dWaCiU?t=4030, great speech, but the link points precisely to the argument), therefore seems smart to me to do such separation anyways. – n-smits Jun 12 '20 at 14:08
  • Btw, vuex *can* be used in js. Simply import it. In your example, `this.$...` is what would break the code. If you eg. `import { file } from '~/base'` where `file` is an object with a prop like `set: (v) => store.commit ...` (and imports store to its file, eg. base/index.js) you have no such problems. (As an example of the architectural boundry Bob is describing). So in the end you do `file.set ...` instead of `this.$store.commit ...` just for starters, and you can also do a lot more neat things. And no need for mapping getters and setters.. – n-smits Jun 12 '20 at 14:21
  • Great speech indeed. I’m not saying it’s wrong in the vue sense to do it, I only wanted to point out that if it’s not wiring into the component, it’s an everyday singleton “service” object. And that’s sufficient and fine. I usually don’t turn such objects into mixins, but that’s besides the point. I still agree with your point, one just has to use it with the restrictions in mind. – János Veres Jun 12 '20 at 14:38
0

You can call methods in mixins only in Vue components. The role of the mixin is to extend the vue component. I would extract the logic from your mixin in a separate service or utility js and then use it in the mixin and service.js

Nikolay Yankov
  • 376
  • 1
  • 4
  • 12