If I have an external package that I'm using, for instance, vue-js-modal. And I import it in /plugins/vue-js-modal.js:
import Vue from 'vue'
import VModal from 'vue-js-modal'
Vue.use(VModal)
Now let's say I have a function that uses vue-js-modal that I want to use in a bunch of different components below:
function showHideModal(showModalName = null, hideModalName = null) {
if (hideModalName) {
this.$modal.hide(hideModalName)
}
if (showModalName) {
this.$modal.show(showModalName)
}
}
Should this function be stored in /plugins/vue-js-modal.js or should it be put into it's own /mixins/showHideModal.js file? Which is more appropriate here and why?
According to plugins document in Nuxt.js website:
Nuxt.js allows you to define JavaScript plugins to be run before instantiating the root Vue.js Application. This is especially helpful when using Vue libraries, external modules or your own plugins.
So if you want to use external modules it's better to have them stored/initiated in plugins, Whereas if you want to have reusable functions for components, you use Mixins which then "Mix" the function and the component together.
Read more about mixins here.
Related
Let's say I want to provide a React component type (Video in this example) that I can import from an "sdk" library and use in another TypeScript React component that lives in a different repo:
import { Video } from "sdk";
export default function MyComponent {
return (
<Video src={...} />
);
}
But I don't want the "sdk" library to contain the implementation for that component. I want the "sdk" to export the type declaration, and I want to mount MyComponent inside a remote-component in another React app, which provides the implementation for everything in "sdk":
import MyVideo from "../my-video";
resolve: {
sdk: {
Video: MyVideo,
},
}
const requires = createRequires(resolve);
export const RemoteComponent = createRemoteComponent({ requires });
Is there a way I can write this sdk library that exports TypeScript types with no implementations, and then use that sdk in another repo with the expectation that the implementation will be available at runtime when the component is mounted? This would be similar to allowing for dynamic linking in C by providing header files in an SDK.
Yes, many libraries originally written in JavaScript offer TypeScript definition files (d.ts). Here's an example: https://github.com/vaadin/web-components/tree/23.3/packages/details/src.
You can enable declaration emit in your tsconfig.json:
{
"compilerOptions": {
"declaration": true
}
}
This will cause the compiler to generate d.ts files.
Please is there a way to create a helper function on a root component in vue and also make the function accessible in all child components?
You can create helper functions and use it as a plugin. In case of you are using nuxt.js, you can create helpers.js in plugins and register it in nuxt.config.js file.
import Vue from 'vue'
import helpers from './helpers'
const plugin = {
install () {
Vue.prototype.$helpers = helpers
}
}
Vue.use(plugin)
In helpers.js, you can define all helper functions.
export default {
cloneObj(val) {
return JSON.parse(JSON.stringify(val));
}
};
Then you can use it in any child components like this:
this.$helpers.cloneObj()
You need to store it in a separate file because it's frustrating to pass it as a prop from one component to another and that's the main idea of why state management like Vuex is a better solution because it provides a centralized state manage which you can access from any component
Is it possible to use a mixin imported from a VueJS plugin in one component?
I've created a plugin and when I import it I can access the mixin's functions from all my components.
Is there a way to make it available in only one component ? or all the plugin add global-level functionality to Vue by definition?
IMHO you should use create 2 things:
the plugin that imports the essentials globally
the mixin that needs to be imported in the components you want
example:
//main.js
import {MyPlugin} from 'my-library'
vue.use(MyPlugin)
in the component
//component.vue
import {MyMixin} from 'my-library'
export default {
mixins: [myMixin],
}
You can register a mixin either globally, either locally. If you don't register a mixin globally, it will be only available in components where it is locally registered. So, with local registration, you can make a mixin available in only specific components.
Registering globally: you just need to declare it in the main.js file
Nb: you don't need to register the mixin in components
Vue 2:
// main.js
import myMixin from './mixins/myMixin'
Vue.mixin(myMixin) // makes the plugin globally available
new Vue({
// ...
}).$mount('#app')
Vue 3:
// main.js
import myMixin from './mixins/myMixin'
const app = createApp(App)
app.mixin(myMixin) // makes the plugin globally available
app.mount('#app')
Registering locally: you do NOT declare it in the main.js file, and you register the mixin in the relevant components
// componentWithMixin.vue
import myMixins from "../mixins/myMixin"
export default {
// ...
mixins: [myMixins] // importing the mixin - without this line, the mixin can't be available
}
I am curious as to the methodology Nuxt.js uses to register a plugin. I have been reading the documentation for Nuxt.js and I am slightly confused as to the registration methodology.
I do not want to register plugins such as vue-flag-icon globally.
My understanding is when we register the plugin we use the plugin folder as such:
import Vue from 'vue'
import FlagIcon from 'vue-flag-icon'
Vue.use(FlagIcon)
I can now use the flag component anywhere in my app - I dont want this!!!
I want to be able to load plugins into the components that need them ONLY.
I have tried loading them as a component like:
components:{
'flag': ()=> import('path to plugin') // #/plugins/vue-flag-icon
}
This does not work.
I changed my plugins script to:
import Vue from 'vue'
import FlagIcon from 'vue-flag-icon'
export default () => {
Vue.use(FlagIcon)
}
And then tried to register the plugin within the components like so:
import flag from '#/plugins/vue-flag-icon';
created(){
flag()
}
My questions really are:
How can I register a plugin within the component without importing the vue instance? (I think is called a bus)
Is it bad practice to import the plugins directly into components?
Is registering all the plugins within nuxt.config.js creating a larger download file for users to download (example: registering vue-twix is not necessary on pages that do not have textareas) or will nuxt/webpack handle the removal of unnecessary plugins on a page by page or component by component basis (so I don't have to even worry about this)?. If this is the case than I dig nuxt.
Thanks
If you want to use FlagIcon only on certain components, you have to import it and use it on every component you want to use.
<template>
<flag iso="ca" />
</template>
<script>
import FlagIcon from 'vue-flag-icon'
export default () => {
components: {
FlagIcon
}
</script>
This should work.
For other components, remember to import any style sheets the component might require:
<style lang="scss" scoped>
#import 'path/to/plugin/style.css';
</style>
I am working on a project that requires using a js plugin. Now that we're using vue and we have a component to handle the plugin based logic, I need to import the js plugin file within the vue component in order to initialize the plugin.
Previously, this was handled within the markup as follows:
<script src="//api.myplugincom/widget/mykey.js
"></script>
This is what I tried, but I am getting a compile time error:
MyComponent.vue
import Vue from 'vue';
import * from '//api.myplugincom/widget/mykey.js';
export default {
data: {
My question is, what is the proper way to import this javascript file so I can use it within my vue component?
...
Include an external JavaScript file
Try including your (external) JavaScript into the mounted hook of your Vue component.
<script>
export default {
mounted() {
const plugin = document.createElement("script");
plugin.setAttribute(
"src",
"//api.myplugincom/widget/mykey.js"
);
plugin.async = true;
document.head.appendChild(plugin);
}
};
</script>
Reference: How to include a tag on a Vue component
Import a local JavaScript file
In the case that you would like to import a local JavaScript in your Vue component, you can import it this way:
MyComponent.vue
<script>
import * as mykey from '../assets/js/mykey.js'
export default {
data() {
return {
message: `Hello ${mykey.MY_CONST}!` // Hello Vue.js!
}
}
}
</script>
Suppose your project structure looks like:
src
- assets
- js
- mykey.js
- components
MyComponent.vue
And you can export variables or functions in mykey.js:
export let myVariable = {};
export const MY_CONST = 'Vue.js';
export function myFoo(a, b) {
return a + b;
}
Note: checked with Vue.js version 2.6.10
try to download this script
import * from '{path}/mykey.js'.
or import script
<script src="//api.myplugincom/widget/mykey.js"></script>
in <head>, use global variable in your component.
For scripts you bring in the browser way (i.e., with tags), they generally make some variable available globally.
For these, you don't have to import anything. They'll just be available.
If you are using something like Webstorm (or any of the related JetBrains IDEs), you can add /* global globalValueHere */ to let it know that "hey, this isn't defined in my file, but it exists." It isn't required, but it'll make the "undefined" squiggly lines go away.
For example:
/* global Vue */
is what I use when I am pulling Vue down from a CDN (instead of using it directly).
Beyond that, you just use it as you normally would.
I wanted to embed a script on my component and tried everything mentioned above, but the script contains document.write. Then I found a short article on Medium about using postscribe which was an easy fix and resolved the matter.
npm i postscribe --save
Then I was able to go from there. I disabled the useless escape from eslint and used #gist as the template's single root element id:
import postscribe from 'postscribe';
export default {
name: "MyTemplate",
mounted: function() {
postscribe(
"#gist",
/* eslint-disable-next-line */
`<script src='...'><\/script>`
);
},
The article is here for reference:
https://medium.com/#gaute.meek/how-to-add-a-script-tag-in-a-vue-component-34f57b2fe9bd
For anyone including an external JS file and having trouble accessing the jQuery prototype method(s) inside of the loaded script.
Sample projects I saw in vanilla JS, React and Angular were simply using:
$("#someId").somePlugin(options)
or
window.$("#someId").somePlugin(options)
But when I try either of those in my VueJS component I receive:
Error: _webpack_provided_window_dot$(...).somePluginis not a function
I examined the window object after the resources had loaded I was able to find the jQuery prototype method in the window.self read-only property that returns the window itself:
window.self.$("#someId").somePlugin(options)
Many examples show how to load the external JS file in VueJS but not actually using the jQuery prototype methods within the component.