How to import external module in vue? - javascript

My code below is working fine:
import Vue from 'vue';
import Vuex from 'vuex';
import user from './modules/auth';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
user
}
});
Is there a shorter way to import a module instead of writing the statement at the top? I instead write it directly inside the modules like below:
export default new Vuex.Store({
modules: {
user: import('./modules/auth'),
}
});
But unfortunately it didn't work (the external module was not imported successfully).

Import with braces is different from import without braces - the latter imports the module statically (at compile time) while the former imports the module dynamically (at run time) and is not an ES6 feature but something specific to Webpack.
You can read more in the Webpack documentation but the most important thing is that dynamic imports (those with braces) return a Promise instead of module reference. The module reference will be available when the Promise resolves. You can read more about lazy-loading Vuex modules in this article https://itnext.io/vue-js-app-performance-optimization-part-3-lazy-loading-vuex-modules-ed67cf555976

Before beginning, I'm using Vue 3 + Vuex 4.
In the file path/to/store/index.js that hold the Vuex store I used the code like this.
// path/to/store/index.js
import { createStore } from 'vuex';
import moduleA from './modules/moduleA';
import moduleB from './modules/moduleB';
export default createStore({
state: {},
mutations: {},
getters: {},
actions: {},
modules: {
moduleA,
moduleB,
},
});
And I created a file for each module as this
// file for each module
export default {
state: { ... },
mutations: { ... },
getters: { ... },
actions: { ... },
modules: { ... },
};

Related

"Property $notify does not exist on type" - Can't use npm package on Vue App

I am using this npm package to send notifications in my Vue App. After following the instructions, and adding the required usages on the main.ts, I keep getting when I try to use the features of it:
Property '$notify' does not exist on type 'Shop'
main.ts:
import Vue from 'vue'
import Notifications from 'vue-notification'
import App from './App.vue'
Vue.use(Notifications)
new Vue({
render: h => h(App)
}).$mount('#app')
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import Character from "./Character.vue";
import Vendor from "./Vendor.vue";
#Component<Shop>({
components: {
Character,
Vendor
},
})
export default class Shop extends Vue {
sellItem(itemID) {
this.$notify({
title: 'Important message',
text: 'Hello user!'
});
}
}
</script>
I have tried importing the component in the .vue file, however it does not recognize the type. What am I doing wrong? I can't find any solution for this...
Thank you.
Add a shim typings file
You need a file that imports and re-exports the type of "Vue", it is named vue-file-import.d.ts, but elsewhere on the internet it is commonly called vue-shim.d.ts. Regardless of name, the content needed is the same:
// vue-file-import.d.ts
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
Try placing the above file in /src location. But sometimes when you move around changing things it might not work so I suggest you to place it inside /typings location

Vue + Jest global config carrying over into spec files

I'm using VueJS and Jest for unit testing my components.
I'm also using the Bootstrap Vue library for styling. I need to use this plugin in my Jest tests in order to remove some console warnings about unknown plugins.
I have created a setup file as so:
import { createLocalVue } from '#vue/test-utils'
import BootstrapVue from 'bootstrap-vue'
const localVue = createLocalVue()
localVue.use(BootstrapVue)
And configured Jest to use this before every test.
setupFiles: ['<rootDir>/tests/unit/setup']
However, to remove the warnings from the console, I need to use the localVue instance when mounting the component:
const wrapper = shallowMount(MyComponent, {
localVue,
propsData: { value: 'someVal }
})
However there is no way that I can see to get the localVue instance created in the setup.js into the test spec files.
If I do this:
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'
Vue.use(BootstrapVue)
It works fine, but this is bad as we should not be using the Global Vue instance in Jest tests.
Is there a way to do what I want to do, or am I going to have to construct the Bootstrap Vue plugins (and others as they come along...) into every single test file?
You could try to assign the localVue variable as a global variable in your setupFiles. This would allow you access localVue variable in every test, like so:
import { createLocalVue } from '#vue/test-utils'
import BootstrapVue from 'bootstrap-vue'
global.localVue = createLocalVue()
global.localVue.use(BootstrapVue)
Then use it like this in your test:
const localVue = global.localVue
const wrapper = shallowMount(MyComponent, {
localVue,
propsData: { value: 'someVal' }
})

How do I access the Vue object within a Vuex module?

In Vue components, I can easily use imported libraries, such as vue-router. I can access the route parameter I need with this.$route.params.myVar. However, if I try to do the same within a Vuex module, I get the error: TypeError: Cannot read property 'myVar' of undefined. How can I extend the Vue object I defined in my main.js to my modules?
Here's my main.js:
import router from './router'
import Vuex from 'vuex'
import myModule from './my.module';
Vue.use(Vuex)
// Register VueX modules
const store = new Vuex.Store({
modules: {
myModule
}
})
new Vue({
router,
render: h => h(App),
store
}).$mount('#app')
And my.module.js:
export default {
namespaced: true,
state: {
...
},
mutations: {
...
},
actions: {
someAction() {
console.log(this.$route.params.myVar)
}
}
}
Obviously, this isn't defined. I tried instantiating a new Vue object at the top of my module like so:
var vm = new Vue()
And changing this to vm, but I get a similar Cannot read property 'myVar' of undefined error. I also tried re-instantiating the route class at the the module:
import route from 'vue-router'
And changing my failing code to route.params.myVar, but I still get the Cannot read property 'myVar' of undefined error.
The way I see it, you have two options.
Pass param.myvar from outside inside vuex action
Import router into vuex module and use it
For the second option make sure to import your router declaration and not the library. For example.
import router from '#/router'
router.currentRoute.params.myVar

destructuring from module imports

I have a index.js in a folder called "vuex" with the following
const module = { state, mutations, actions, getters }
export default { module, plugin }
state, mutations, actions were imported from another file
I'm trying to get the "state" property in another file so I
import module from './veux'
then
const { state } = module
however state is undefined which is weird because console.log(module) shows me that module.state is present
I'm new to this ES6-7 flow so but what exactly am I doing wrong here?
Since you have exported the object {module, plugin} as default export
after importing like
import module from './veux'
module will have structure like
module = {
module: { state, mutations, actions, getters },
plugin
}
so in order to access state, you will write module.module.state or
const {module: {state}} = module; // nested destructuring
console.log(state)
an easier to understand and readable method would be to export your module with named export like
export const module = { state, mutations, actions, getters }
export default plugin
and import it like
import plugin, { module } from './veux'
after which you can do
const { state } = module;
I'm trying to get the "state" property in another file so I
import module from './veux'
const { state } = module
however state is undefined which is weird because console.log(module)
shows me that module.state is present
No, you're importing the whole default-exported object (with its module and plugin properties) as module. The property would be module.module.state.
I have a index.js in a folder called "vuex" with the following
const module = { state, mutations, actions, getters }
export default { module, plugin }
Don't. Use named exports for exporting multiple things:
export const module = { state, mutations, actions, getters }
export { plugin }
then you can do
import { module } from './veux'
const { state } = module
It'll work if you do this:
import { module } from './veux';

Webpack ES6 modules circular dependencies when using index files

I have a big project, I try to refactor to ES6 modules right now.
To make further development easier, I wanted to introduce index files, which just export all modules within the directory:
index.js:
export { default as ModuleA } from './moduleA'
export { default as ModuleB } from './moduleB'
export { default as ModuleC } from './moduleC'
moduleA.js:
import { ModuleB } from './index'
moduleB.js:
import { ModuleC } from './index'
ModuleC.doSomething()
moduleC.js:
export default {
doSomething: () => {}
}
Starting point is ModuleA.
The problem is, that in ModuleB ModuleC is undefined, so doSomething can't be executed.
I suspect some issues with circular dependencies, since moduleB tries to access the index again, which parses moduleB before moduleC.
Is it just not possible to do this, or is there another solution?
The issue here is that ModuleC has not been exported by the time that ModuleB is exported and runs, and since ModuleC is a requirement of ModuleB, it can't run. If I were you, I would just export each of them from their own files, and when you import them, import them from their own files instead of index.js.
Example
ModuleA.js:
import { ModuleB } from 'moduleB.js'
export default {
// Your code here
}
ModuleB.js
import { ModuleC } from 'moduleC.js'
moduleC.doSomething();
ModuleC.js
export default {
doSomething: () => {
// Your code
}
}
And finally, since ModuleA is the entry point from index.js, just import it into index.js and run what you need to run.
Alright. Solved it.
The problem ist, that when ModuleB tries to import ModuleC from the index, the index will be parsed again and will see ModuleB before it can reach ModuleC.
It seems to work with only two modules, since the index file doesn't get reparsed, I think.
The solution:
Import modules, which try to load other modules from the index file at last.
So index.js should look like this:
export { default as ModuleA } from './moduleA'
export { default as ModuleC } from './moduleC'
export { default as ModuleB } from './moduleB'

Categories