How to import javascript library in main.js for global availability throughout vue app? - vue.js

My main.js contains import "mathjs"; and seems to be working fine within main.js as
console.log(median(5,4,6,1));
> 4.5
median() is however not available outside of main.js, i.e. in components. After reading this answer, I assumed that the simple import should be enough for global availability throughout the vue app?

In general when you are working with modern modules or a bundler like webpack, you have to import mathjs in every module (think file) you want to use it.
What is often done in the vue context, is adding the library to the Vue context itself with a plugin.
See https://v3.vuejs.org/guide/plugins.html#writing-a-plugin
So this should be as easy as:
const mathjsPlugin = {
install(app){
app.config.globalProperties.$mathjs = mathjs;
}
}
const app = createApp(...);
app.use(mathjsPlugin);
// inside of a component
export default {
created(){
console.log(this.$mathjs....);
}
}
I personally think explicitly importing is a cleaner approach, but if mathjs is used in most of the components, this approach can make sense

in main.js import all as math then add it as global property :
import * as math from 'mathjs'
const app=createApp({....})
app.config.globalProperties.$math =math
then in any component you could use it like this.$math.theFunctionName

Related

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

Can not read property "document" of undefined - ApexCharts

I'm attempting to import apexcharts into my nuxt project. I've used both the vanilla lib and vue wrapper.
Simply importing the library causes the following error
Like I said, i've attempted importing both
import ApexCharts from "apexcharts"
and
import VueApexCharts from "vue-apexcharts"
Both return the same error.
Is this something I have to configure in the nuxt.config.js file?
This is because you are using Nuxt.js which does SSR for you. Since document does not exist on the server-side it will break.
To work around it there a couple of approaches:
First you can create a plugin/apex.js which is responsible for registering your components
import Vue from 'vue';
import ApexChart from 'vue-apexcharts';
Vue.component('ApexChart', ApexChart);
and in your nuxt.config.js make sure to load the plugin file on the client-side:
module.exports = {
// ...
plugins: [
// ...
{ src: '~/plugins/charts', ssr: false }
],
// ....
};
Now you can reference the ApexChart component anywhere in your app, also make sure to wrap it with ClientOnly component to prevent Nuxt from attempting to render it on the server-side:
<ClientOnly>
<ApexChart type="donut" :options="chartData.options" :series="chartData.series" />
</ClientOnly>
The other approach is you can import Apex charts as async components, which do not get rendered on the server-side, but it has been a hit and miss with this approach, feel free to experiment.
Generally when using Nuxt or any SSR solution, be careful of the libraries you use as they might have an implicit dependency on the execution environment, like requiring browser-specific APIs in order to work like window or document.

Where to import file js in vue/nuxt

Usually I use a js code with functions to run on some events.
Now I am using nuxt.js and I wonder where to put this file or how to create a global method to use these functions in every component.
I could write the methods that I need inside every a specific component but after it wouldn't be usable outsite of it.
How to do that in vue/nuxt?
So one way to do it in vue.js is by using mixins, in nuxt you can also use mixins, then you should register them as plugins, but first:
Non global mixins
Create an extra folder for your mixins. For example in a /mixins/myMixin.js
export default {
methods: {
commonMethod() {
console.log('Hello')
}
}
}
Then import in a layout, page or component and add it via the mixins object:
<script>
import myMixin from '~/mixins/myMixin.js'
export default {
mixins: [myMixin]
}
</script>
Global mixins
For example in a new file plugins/mixinCommon.js:
import Vue from 'vue'
Vue.mixin({
methods: {
commonMethod() {}
}
})
Include the file in nuxt.config.js like that:
plugins: ['~/plugins/mixinCommon']
After that you would have the method everywhere available and call it there with this.commonMethod(). But here an advice from the vue.js docs:
Use global mixins sparsely and carefully, because it affects every
single Vue instance created, including third party components. In most
cases, you should only use it for custom option handling like
demonstrated in the example above. It’s also a good idea to ship them
as Plugins to avoid duplicate application.

How to import anime.js to my Vue project?

I have a question regarding importing an anime.js into my vue project. I am using vue cli. How do I include animejs to my project? I tried it this way:
import anime from 'animejs'
Vue.use(anime);
but I get an error in the console that says:
Uncaught TypeError: a.hasOwnProperty is not a function. . .
can you guys help me?
Vue.use() is used only for plugins designed for Vue.js. You can't simply add a library there, it won't work.
My suggestion is that you create that plugin and use it on your project to make anime.js acessible everywhere.
You could do it like this:
//vue-anime.js
import anime from 'animejs';
const VueAnime = {
install (Vue, options) {
Vue.prototype.$animeJS = anime;
}
}
export default VueAnime
Then later
import VueAnime from './vue-anime';
Vue.use(VueAnime);
Now every Vue component will be able to use anime acessing this.$animeJS.
Or simply -
import Vue from "vue";
import anime from 'animejs/lib/anime.min.js';
Vue.prototype.$anime = anime;
Then this.$anime in all components
#Phiter's answer looked good at first, but I wasn't able to get it to work in my vue-cli 3 environment. The below code worked though, so I think it may work for you. This is just a simple way to install an external library into your Vue app and expose it through a prototype:
// animejs.js
import anime from 'animejs'
const install = (Vue, options) => {
Vue.prototype.$animejs = anime
}
export default install
// Then, in your main.js (at least for me)
import VueAnime from './animejs'
Vue.use(VueAnime)
Now, when you need to access the library, just use this.$animejs in your project.
or simply like this in main.js after npm install:
import anime from 'animejs';
Object.defineProperty(Vue.prototype, '$anime', { value: anime });
then use this.$anime tu use it.
To use AnimeJS globally in Vue 3 project, just create a plugin (plugins/anime.js):
import anime from 'animejs';
export default {
install(app, options) {
app.config.globalProperties.$anime = anime;
},
};
Then include it (main.js or elsewhere):
import VueAnime from './plugins/anime';
createApp(App)
.use(VueAnime)
.mount('#app');
And now, it's accessible everywhere by this.$anime.
Please notice that a minor change from the previous version is installing the plugin for Vue 3.

Custom js library(scrollMonitor) inside main Vue instance to be shared with inner components

This is Vue.js question, generally I'm trying to use 'scrollMonitor' function inside of my .vue instance(imported via main.js) but it gives me a typical 'this.scrollMonitor is not a function' error
mounted () {
let watcher = this.$scrollMonitor(this.$refs.nicer)
}
In main.js ScrollMonitor library seems to be properly imported(console shows what's expected):
import scrollMonitor from 'scrollmonitor'
Vue.use(scrollMonitor)
console.log(scrollMonitor)
Again main goal is using scrollMonitor functionality inside of .vue file(in vue component instance). Sorry if I'm missing something silly here - I'm already using some other libraries like Vue-Resource in that file so issue is not in 'filepath' but rather in the way I'm using scrollMonitor functionality, any help is much appreciated, thank you !
For those who are still looking: there is a way of adding plain js libraries to the main.js and then using them with ease globally in inner components(this is not about mixins):
import scrollmonitor from 'scrollmonitor'
Object.defineProperty(Vue.prototype, '$scrollmonitor', {
get() {return this.$root.scrollmonitor}
})
also it should be added to main Vue data object:
data () {
return { scrollmonitor }
},
And then it can be used within mounted() callback (not created() one) inside of the component itself, with scrollmonitor it may look like this(in my specific case the template had a div with ref="nicer" attribute, 'create' is a method specific to the library api):
mounted () {
this.$scrollmonitor.create(this.$refs.nicer)
}
Hooray, I hope someone may find this useful as I did!
Are you using a plain javascript library and trying to Vue.use it? That won't really work. Vue.use will only work with plugins designed to work with Vue. Import the library into the component that needs and and just use it there.
scrollMonitor(this.$refs.nicer)