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

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

Related

How can get Object mounted on vue2.7 instance?

I have just completely upgraded my project to Vue2.7, which a backported support for Vue3 feature.
Like what I try is, get the object the in vue instance chain, such as
import Vue from 'vue'; Vue.prototype.$http = http; but no any method or hook such as createApp supported in vue2.7, so how to I access it(the $http) in my component?
only what I can do for now just console.log(getCurrentInstance()).
And finally get it by getCurrentInstance().proxy.__proto__.__proto__.$http, such unpleasant code, is it any other better shortcut to do this? Thanks.
I would suggest using provide/inject to make the axios available in all your components.
https://vuejs.org/guide/components/provide-inject.html
Find out the way by warmed-heart people Jacek, just use provide and inject to solve it.
Just like
const vue = new Vue({
setup() {
provide('http', http)
}, ...
}

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

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

Vue 3 access to app level provided instances from vue-router

I want to write some complicated guard logics in vue-router in Vue 3 to protect entering some routes according to store and my other provided modules. For example, I want to check if user profile info is present or not:
router.afterEach((to, from) => {
console.log('store: ', useStore());
const puex = usePuex();
puex.isReady().then(() => {
const me = puex.me.compute();
watch(me, (...params) => console.log('router: ', ...params));
});
});
In the above code, useStore and usePuex both try to inject store and puex instances from Vue app which are provided while being used in main.js bootstrap. But both use functions return undefined and I guess that the inject in this scope searches a different place where app-level provided instances do not exist.
So how can I inject them in the router file, or in other words how can I get store and puex instance using useStore and usePuex here?
I have found a way according this question but I still don't know if it is the best available solution. I can export the app instance from main.js file and then use app.$store and app.$puex instead. Although it works, I still think about a better solution to inject the store and puex instance using use functions (inject).
You still can add the navigation guards after that your app has mounted in main.js/ts, the code would look like:
// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
const vm = createApp(App)
.use(puex)
.use(router)
.mount('#app');
router.afterEach((to, from) => {
const me = vm.puex.me.compute();
watch(me, (...params) => console.log('router: ', ...params));
});
You still can export that vm, to import it in the router file and use it the same way, but I really find somehow confusing, as main.js/ts is already importing the router file.

State management in vue3 with vuex4 fails - Code shared in codesandbox

Dear friends of the modern lightweight web, I hope you can help a noobie regarding vue3 and Vuex 4.
I share timetable details (array of objects/dictionary) between multiple child components, which then can be displayed (e.g. Top 5 work) or edited (e.g. add new work details) in a way that these changes get reflected in all the other components. For this, I tried to use Vuex 4.
I am not able to access the state in a component. For debugging reasons, I even added a dummy entry during the creation of the state.
https://codesandbox.io/s/dazzling-brahmagupta-5sn1t?file=/src/main.js
Your demo uses Vuex 3 (perhaps that was a mistake only in the demo). Be sure to install Vuex 4, which provides the createStore() method:
npm i -S vuex#4
Also, the result of createStore() should be passed to app.use(), which is an instance method of the app from createApp() (not the App.vue component):
import { createApp } from 'vue'
import { createStore } from 'vuex'
import App from './App.vue'
const store = createStore(/*...*/)
// App.use(store) ❌ don't do this
createApp(App)
.use(store) ✅
.mount('#app')
demo

Problem when importing js-cookies in Main.js

I'm trying import js-cookies in my main.js
Main.js
import * as Cookies from "js-cookie";
Vue.use(Cookies)
Using in component
this.$Cookies.set('name', data.user, { secure: true });
Error
TypeError: Cannot read property 'set' of undefined
what is the problem?
I have tried a thousand ways and it still does not work.
Vue.use(name) is used to install a vue plugin. The package will need an install method that receives a vue instance.
#1
You can use the cookies packages without a plugin importing the module in the component
<script>
import Cookies from 'js-cookie';
export default {
methods: {
addCookie() {
console.log('adding the cookie');
Cookies.set('chocolate', 'chookies');
console.log(Cookies.get());
}
}
}
</script>
#2 you can add a VUE plugin and set a Cookies prototype function to the Cookies module.
(Prototype vue functions will be available for components, it's standard to prefix them with $).
src/CookiesPlugin.js
import Cookies from 'js-cookie';
const CookiesPlugin = {
install(Vue, options) {
Vue.prototype.$Cookies = Cookies;
}
};
export default CookiesPlugin;
src/main.js
import CookiesPlugin from './CookiesPlugin';
Vue.use(CookiesPlugin);
In the component
this.$Cookies.set('chocolate', 'chookies');
console.log(this.$Cookies.get());
You are using a NOT Vue (Vanilla JS library) library and you are trying to use it as a Vue resource.
Try using this one instead