I have a vue-cli project. It means, I have 1 .vue file and main.js.
I want to call method from .vue file in main.js
But I get error that function is not defined.
How can I call inside .vue file method in main.js?
Method should be defined in .vue file NOT in main.js in new Vue{}.
I don't believe you can do it exactly the way you are asking as the .vue component is child of the parent instance defined in the main.js file and is out of scope. What you can do is define the function or functions you want to use in this way as a mix-in.
Create a separate js file to define your mixin like follows
var myMixin = {
data: function () {
return {
//
},
methods:{
myAwesomeMethod(){...}
}
}
Then import it in your main js like so:
import myMixin from '/mixins/myMixin.js';
Then reference it in your Vue instance
new Vue({
mixins: [myMixin],
})
After than you can call the method in your main.js using this.myAwesomeMethod
Alternatively you can define your mixin like follows and only import it with no need to reference it.
Vue.mixin({
methods:{
myAwesomeMethod(){
//...
}
}
});
I don't recommend it, however, if you absolutely cant make any modification to the main.js file, then you could simply define your mixin using the latter method directly in your .vue file outside of the definition for your component.
<script>
// define your mixin
Vue.mixin({
methods:{
myAwesomeMethod(){
//..
}
}
});
// define your component
export default {
data: function () {
return {
}
}
}
</script>
Then the mixin should be available to be called anywhere.
Related
I have a Mixin file like this:
export default {
data: function() {
return {
analysisTime: "nothing",
phantomPrefix: "One more",
}
},
methods: {
isGeneric: function() {
return this.phantomPrefix
},
}
}
Whenever I call Mixin.js its methods are accessible but the $data variable is returning undefined.
For example, Whenever I called isGeneric function it's returning undefined instead of 'one more' because it's returns this.phantomPrefix.
Ps: If I access the same method of Mixin.js file from another component let's say Example.Vue it's working fine for me.
I have imported the Mixin file in store.js like:
import Mixin from "./mixins/Mixin";
and calling method like this: Mixin.methods.isGeneric()
Store.js file contains:
import Vue from "vue";
import Vuex from "vuex";
import tmpMixin from "./mixins/tmpMixin";
Vue.use(Vuex);
let vue_plugins = [];
export default new Vuex.Store({
plugins: vue_plugins,
state:{},
action:{
get_snippet_data_using_tomograph: function(data) {
let output = tmpMixin.methods.isGeneric()
}
}
});
Vue mixins are made for Vue components, it's not compatible with a Vuex module.
A mixins expect a Vue component instance, which is not provided by Vuex when you import it like this.
If you need to have a reusable code between a Vuex store and Vue components, you still can create a simple js file that exports a functions. But it won't be reactive or have a current state because it's not a Vue component.
I developed a plugin to centralize HTTP calls and need to access its function ($api) from an imported module in a component.
The following works fine:
The plugin (http-transport.js)
export default {
install: function (Vue) { ...
Vue.prototype.$api = (...)
main.js
import HTTPTransport from './http-transport/http-transport'
Vue.use (HTTPTransport);
Usage from any component.vue
methods: {
someMethod() {
this.$api(...)
}}
All the above works.
Now, I have a SFC component that imports a module
component.vue
import logic from "./LogicService.js";
The question: how can I call $api from a function within LogicService.js?
The real case is that LogicService.js imports DataService.js from which I need to call the $api function, but I guess the solution to the question solves this as well.
Thanks so much!
(vue 2.6.11)
there are couple ways to do that.
the most easy way is just import vue and call the function. but for that case you must add the plugin function as global to vue
for example. in http-transport.js
export default function (Vue) {
//add global method or property
Vue.api= function () {
// some logic ...
api();
}
//add an instance method
Vue.prototype.$api= function () {
// some logic ...
api();
}
}
function api(){
//code goes here
}
and then in your js files just import Vue and call Vue.api().
for example in LogicService.js
import Vue from "vue";
export default function(){
//call api
Vue.api();
}
the problem with this way is that you can access Vue.api only when vue finish installize (most cases that the case so no problem).
a second way you can do that is to write the plugin like that
export default function (Vue) {
//add global method or property
Vue.api= function () {
// some logic ...
api();
}
//add an instance method
Vue.prototype.$api= function () {
// some logic ...
api();
}
}
export function api(){
//code goes here
}
now the plugin is actually indepent of vue and can work by itself without vue. for example now you can do that in LogicService.js
import {api} from './http-transport.js'
api()
OK, i have a web page with some steps for the user and a mixin that handle those steps properties and logic, like current/next step value, checks to enable user advancing from each step to the next, etc.
Now i have to add a new functionality to be executed only after a certain step, so what i would like to be able to do is to call the original mixin method that is called everytime the user advance to the next step to add this functionality.
To be more clear, the mixin is (obviously) used in many pages of the webapp, so i would like to override the culprit mixin method in the component extending it, call the original mixin method to reuse its logic and then call oher methods for the new functionality.
Is it possibile?
sure you can, try it so:
// MyMixin.js
export default {
methods: {
myMethod() {
//...
}
}
}
// Component.vue
<script>
import MyMixin from 'path-to-mixins/MyMixin'
export default {
//...
mixins: [MyMixin],
methods: {
// there is overrinding you mixin method called myMethod
myMethod() {
// then some logic before to use your mixin method
// and call your mixin method as below
MyMixin.methods.myMethod()
}
}
//...
}
</script>
The previous answer does not work, in many cases...
you can directly access the function from the import but you need to bind the scope to this so the function uses your component data and/or other overriden functions
// Mixin.js
export default {
methods: {
aMethod() {
//...
}
}
}
// Component.vue
import Mixin from './Mixin'
export default {
//...
mixins: [Mixin],
methods: {
aMethod() {
// you need to bind the method to `this` when running so that the mixin uses your component data.
Mixin.methods.aMethod.call(this);
}
}
//...
}
if the mixin you are importing is already a vue constructor, this can happend if you used Vue.extend to create the mixin, in this case you need to use the options to access your method
You can access the mixin function using the options of the mixin
// Mixin.js
export default Vue.extend({
extends: OtherComponent
methods: {
aMethod() {
//...
}
}
})
// Component.vue
import Mixin from './Mixin'
export default {
//...
mixins: [Mixin],
methods: {
aMethod() {
// you need to bind the method to `this` when running so that the mixin uses your component data.
Mixin.options.methods.aMethod.call(this);
}
}
//...
}
I have a bit of code that makes an api call to a server and returns some JSON.
It did exist as a method in my component but as it is getting a bit long I want to extract it to it's own file
In vuejs what is the best practice here.
should it be a component without a template? How would this work?
will I just create an es6 module?
I would suggest using a mixin here.
In a file like myCoolMixin.js define your mixin...
export default {
methods: {
myAwesomeMethod() {
//do something cool...
}
}
}
You can define anything in a mixin just like a component. e.g. data object, computed or watched properties, etc. Then you simply include the mixin in your component.
import myCoolMixin from '../path/to/myCoolMixin.js'
export default {
mixins: [myCoolMixin],
data: function() {
return: {
//...
}
},
mounted: function() {
this.myAwesomeMethod(); // Use your method like this!
}
}
More on Mixins here: https://v2.vuejs.org/v2/guide/mixins.html
Mixins work, or you could create a plugin. Here's the docs example:
MyPlugin.install = function (Vue, options) {
// 1. add global method or property
Vue.myGlobalMethod = function () {
// something logic ...
}
// 2. add a global asset
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// something logic ...
}
...
})
// 3. inject some component options
Vue.mixin({
created: function () {
// something logic ...
}
...
})
// 4. add an instance method
Vue.prototype.$myMethod = function (methodOptions) {
// something logic ...
}
}
Vue Plugins
I am using nuxt.js. I have a helper.js script inside plugins folder which has a simple Test() function. Now how can I can call the Test() method inside pages which is in helper.js file.
helper.js file:
export default function Test() {
return 'This is test'
}
to access your global methods entire application:
1-create ./plugins/helpers.js .
2-edit ./plugins/helpers.js :
import Vue from 'vue'
Vue.mixin({
methods:{
mySpecialMethod(value){
console.log(value)
},
}
})
3-edit ./nuxt.config.js :
plugins: [
...
{ src: '~/plugins/helpers' },
...
],
now you can access your global method by:
this.mySpecialMethod()
Using the inject method
There is actually an easy way to do this by using the 'inject' method.
As described in the docs...
The plugins directory contains JavaScript plugins that you want to run before instantiating the root Vue.js Application. This is the place to add Vue plugins and to inject functions or constants. Every time you need to use Vue.use(), you should create a file in plugins/ and add its path to plugins in nuxt.config.js.
in your plugin simply use inject like this:
export default ({ app }, inject) => {
inject('myInjectedFunction', (string) => console.log('That was easy!', string))
}
and in your components you can use it as follows:
export default {
mounted(){
this.$myInjectedFunction('works in mounted')
},
asyncData(context){
context.app.$myInjectedFunction('works with context')
}
}
"Manual" injection
If you plan on injecting something yourself check out the Vue Docs on Adding 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
Vue.prototype.$appName = 'My App'
And prefix these injected properties with '$'...
$ is a convention Vue uses for properties that are available to all instances. This avoids conflicts with any defined data, computed properties, or methods.
If you just want to use the code in your components (pages), you only need to import and use the method:
TestPage.vue
<template>
<div>
<h1>{{ getTest }}</h1>
</div>
</template>
<script>
import test from '~/plugins/helper.js'
export default {
computed: {
getTest () {
return test()
}
}
}
</script>
Hello you can inject the function globally into Vue doing the following:
./plugins/myPluging.js
import Vue from 'vue'
Vue.prototype.$nameOfMyPlugin = (args) => {
// Code here
}
Them in all your components you can access it this way:
./components/myComponent.vue
<script>
export default {
name: 'c',
mounted () {
this.$nameOfMyPlugin('something useful')
}
}
</script>
And that's it :) hope this helps.
-- Reference: https://nuxtjs.org/guide/plugins/#inject-in-root-amp-context
Below is a a custom js plugin that I have used in one of my nuxt projects.
create your file inside the plugins folder, and make your own function as below
export default (context, inject) => {
const formatDate = (dateTime) => {
if (typeof(dateTime) === 'undefined' || dateTime === null) {
return null;
}
let tempDate = new Date(dateTime);
tempDate.setMinutes(tempDate.getMinutes() -
tempDate.getTimezoneOffset());
tempDate = tempDate.toISOString().slice(0, 16);
return tempDate;
}
// Inject $hello(msg) in Vue, context and store.
inject('formatDate', formatDate)
// For Nuxt <= 2.12, also add 👇
context.$formatDate = formatDate
}
Add the plugin to nuxt.config.js and you will be able to use it globally.
myPlugin.js
export default (_, inject) => {
const myFuncA = value => return value;
const myFuncB = value => return myFuncA(1) + value;
inject('myPlugin', { myFuncA, myFuncB }
)
nuxt.config.js
plugins[
'#/plugin/myPlugin.js'
]
myComponent.vue
created(){
console.log( this.$myPlugin.funcA(2) );
}
in myPlugin.js, instead of "_" can use some public nuxt variables like {$config}