How to use Axios in main.js - vue.js

I am learning Vue.js.
I have this code which runs fine :
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
const app = createApp(App).use(store).use(router)
app.mount('#app')
Now I would like to add some import, for example 'axios'. This code does not run :
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios'
const app = createApp(App).use(store).use(router).use(axios)
app.mount('#app')
The error is:
Uncaught RangeError: Maximum call stack size exceeded
at merge (utils.js?c532:276)
at assignValue (utils.js?c532:282)
at forEach (utils.js?c532:253)
at merge (utils.js?c532:291)
at assignValue (utils.js?c532:282)
at forEach (utils.js?c532:253)
at merge (utils.js?c532:291)
at assignValue (utils.js?c532:282)
at forEach (utils.js?c532:253)
at merge (utils.js?c532:291)
So how to add some other "use" in the main.js file ? It is certainly very basic but I am a beginner.

You're using vue 3 and axios is not a plugin (we cannot register it like app.use()) it's a javascript module that could be add to the app instance like :
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios'
const app = createApp(App).use(store).use(router)
app.config.globalProperties.axios=axios
app.mount('#app')
and in child component reference it like :
this.axios

Note: the code below is valid for Vue 2.x. Since version 3, some stuff has changed regarding initialization (createApp function is now required).
What I usually do in my code is the following:
import Vue from 'vue';
import axios from 'axios';
// Add it to Vue prototype (use any variable you like, preferrably prefixed with a $).
Vue.prototype.$http = axios;
// Instantiate the main vue app.
let app = new Vue({
//
});
This means that the $http object is now available in all your components using this.$http. Since it is assigned as a prototype variable, it is considered a singleton (it is re-used everywhere), so you can add any options you need to the axios variable before assigning it to Vue.prototype.$http.
Additionally:
Vue.use() is made specifically for enabling Vue plugins. That means the given parameter must use the exact syntax as described here https://v2.vuejs.org/v2/guide/plugins.html . Since axios is not a Vue plugin but just a regular JavaScript library, you cannot use it with this function.
If you want to make it especially nice (or convoluted), you can use the following syntax:
Vue.use({
install(v) {
v.prototype.$http = axios;
// Do other stuff like adding mixins etc.
}
})
This may clear up your code if you move this code to another file, so it could end up like this:
import myCustomAxiosLoader from './bootstrap/axios';
Vue.use(myCustomAxiosLoader);

Related

Transition from gobal Vue instance to app breaks import dependency

I'm looking at migrating a Vue 2 app to Vue 3 and ran into a problem. The Vue 2 app used to start with importing a whole lot of components and directives:
// these components register to the global Vue instance
import {ComponentA} from './componenta';
import {directiveA} from './directivea';
// create app (after the components are registered)
new Vue({...})
This worked fine, but when changing this code to Vue3, the app instance is now created instead. This instance isn't actually available when the global directives and components are imported.
What's the recommended way for dealing with this? I can't reorder the imports to the bottom of the file as webpack bundles them always at the top...
The order of imports does not matter in your case - what matters is the order of the JavaScript statements that follow the import section.
You should first create the app instance and only then register your global components to this instance - as explained in https://learnvue.co/2020/08/how-to-register-a-vue3-global-component/
import { createApp } from 'vue'
import PopupWindow from './components/PopupWindow'
import App from "./App.vue"
const app = createApp(App)
app.component('PopupWindow', PopupWindow) // global registration - can be used anywhere
app.mount('#app')
I settled with a solution that imports the app instance before component registration/definition (which occur within the component file) in an attempt to keep the current structure.
import {app} from './instance';
import './components/popupwindow';
import App from './app.vue';
const app = createApp(App)
app.mount('#app')
// instance.js
import {createApp} from 'vue';
const app = createApp();
export {app};
// popupwindow.vue
import {app} from '../instance';
// component registration+definition here (for global components only)
app.component('popup', {
...
}

How to use Realm SDK with vue3

i have use realm sdk in vue2 with this syntax
// file scr/plugins/realm.js
import Vue from 'vue';
import {App} from 'realm-web';
Vue.prototype.realmApp = new App({id: 'artes-realm-vl12'})
//file scr/main.js
import './plugins/realm';
but in Vue3 this syntax is't working anymore can you please help me how to solve with this problem thank you
In main.js add that app as global property :
import {createApp} from 'vue'
import {App} from 'realm-web';
import app from './App.vue'
const myApp=createApp(app)
myApp.config.globalProperties.realmApp = new App({id: 'artes-realm-vl12'})
myApp.mount('#app');

How to include a library to be available in whole Vue.js 3 project?

According to this blog post the correct way of including frequently used libraries (e.g. axios) in Vue.js 2 is to set them as property of Vue prototype object like this:
import axios from 'axios';
Object.defineProperty(Vue.prototype, '$axios', { value: axios });
Unfortunately, this approach is not working in Vue.js 3 anymore. So what is the correct way of importing library to be accesible in whole project? I would prefer not to set them as global variable (i.e. to the window object.)
To use provide/inject as an alternative
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios';
const app = createApp(App)
app.provide('axios', axios ) // <-- define here
app.mount('#app')
Then in any component you wanna use axios you would do this
app.component('todo-list-statistics', {
inject: ['axios'],
created() {
this.axios // --> Injected property
}
}
I think the best way to us a library in a vue 3 project is to use the depency injection
https://v3.vuejs.org/guide/component-provide-inject.html
however I simply recommend that you import the library where you really need it, to have a more accurate intellisense, and a better three-shaking

TypeError: this.Vue.axios is undefined when using axios HTTP driver

Using vue-auth (vue-auth on GitHub) with the Axios HTTP driver I get the following error in the browser console:
TypeError: this.Vue.axios is undefined
main.js
import Vue from "vue";
import App from "./App.vue";
import axios from "axios";
import "./libs/vue-auth";
./libs/vue-auth.js
import Vue from "vue";
import vueAuth from "#websanova/vue-auth";
import bearer from "#websanova/vue-auth/drivers/auth/bearer";
import axiosHttp from "#websanova/vue-auth/drivers/http/axios.1.x";
import vueRouter from "#websanova/vue-auth/drivers/router/vue-router.2.x";
// Vue.axios = axios;
Vue.use(vueAuth, {
auth: bearer,
http: axiosHttp,
router: vueRouter
// ...
});
When removing the comment for Vue.axios = axios; it seems to work at first glance. So I thought moving Vue.axios = axios; to the main.js but then again it's not working.
Vue.axios can be assigned either manually or with vue-axios plugin. Since #websanova/vue-auth/drivers/http/axios.1.x expects it to exist on plugin initialization:
import Vue from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
...
Vue.use(VueAxios, axios)
Vue.use(vueAuth, ...)
Moving Vue.use(VueAxios, axios) to main.js won't work because it should be evaluated before ./libs/vue-auth is imported, and it cannot precede import according to JS specs. Vue.use(...) should either moved to main.js together, or they both should be located in ./lib modules.

use axios globally in all my components vue

I am testing with axios within a Vue application and the CLI. I've been using vue-resource and I could access it on all my components by simply passing it to Vue.use (VueResource). How can I achieve this with axios, so I do not have to import it into a component, but simply define it once in the main.js file?
In main.js you can just assign Axios to $http.
main.js
import Axios from 'axios'
Vue.prototype.$http = Axios;
By modifying the vue prototype, any vue instance will have the ability to call $http on this. (e.g. this.$http.get('https://httpbin.org/get')
Note: $http is the axios object now, so any method you can call on axios object, you can call on this.$http.
NOTE: When Vue module is installed as a package and not using through CDN then this approach works fine else if importing Vue from CDN then we have both options, first the answer here and second is to import Vue in main.js and then use Vue.prototype.{variable}=Axios
For VUE3, you need to add below code:
Syntax:
app.config.globalProperties.{variable} = value;
Example:
app.config.globalProperties.$http = Axios; // Allow axios in all componenets this.$http.get
In your main.js or app.js
/**
* Importing libraries & componenets
*/
import { createApp } from 'vue';
import { createWebHistory, createRouter } from 'vue-router';
import Axios from 'axios';
/**
* Vue initialization
*/
const app = createApp({
components: {
Index
},
});
app.use(router);
app.config.globalProperties.$http = Axios; // Allow axios in all componenets this.$http.get
app.mount('#app');
You can call the GET method same as VUE2 in your components: this.$http.get('https://httpbin.org/get')
For all those who implement from zero (whithout deprecated vue-resource), another simple and efficient way, the "Laravel way" too.
In CLI run: npm install axios
In main.js define:
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.axios.defaults.headers.common['Accept'] = 'application/json';
and then you can use it in any component like this:
window.axios.get('https://example.com').then(r => console.log(r.data));
and capture r.data output
(if you use the Laravel routes instead of those of Vue you can use it like this: axios.get(url).then(...)
What worked for me in the end was this:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import axios from 'axios'
import VueAxios from 'vue-axios'
const app = createApp(App).use(router)
app.use(VueAxios, axios)
app.mount('#app')
And I used this library:
vue-axios