What is the purpose of Vue.use() while importing a plugin? If we have already used vue.use , is it required to add it to the components - vue.js

I'm using the plugin vue-flag-icon - https://www.npmjs.com/package/vue-flag-icon for flags, In their documentation I saw the following steps for initialising.
import FlagIcon from 'vue-flag-icon'
Vue.use(FlagIcon);
Do I need to have this? This is not specified in their docs!
export default {
components: {
FlagIcon. /// do i need to give it here ?
},
}
What is the purpose of this Vue.use(...), It's working fine even if I remove that. Can somebody help me out?
Checked the vue documentation - https://v2.vuejs.org/v2/guide/plugins.html.
Did not get a clear idea about it

Vue.use automatically prevents you from using the same plugin more than once, so calling it multiple times on the same plugin will install the plugin only once.
For the flag component, it declares a global component that you can refer within your components, such that in the following example will render correctly.
in vue-flag-icon source code
install: function (Vue) {
if (VuePlugin.installed) {
return;
}
VuePlugin.installed = true;
Vue.component('flag', Flag);
}
You can see that with Vue.component('flag', Flag) that this is a root level component declaration, therefore, in your components, you do not require to declare something like following
Unnecessary if using Vue.use
import { Flag } from "vue-flag-icon"
export default {
components: { Flag }
}
If Vue.use is not used, the flag tag in the template will throw an error if you do not include it as a component within your vue init.
<template>
<div id="app">
<img src="./assets/logo.png">
<flag iso="it" />
<flag iso="gb" />
<flag iso="us" />
</div>
</template>
<script>
export default {
name: 'app',
}
</script>

Related

jsPlumb integration with Nuxtjs throwing the error document is not defined

I know there are a few questions similar to this but they did not work for me so I am posting this.
I am trying to add jsPlumb into my Nuxtjs/Vuejs application. I did the following steps:
npm i jsplumb --save
Create a Vuejs page and add the simple code:
<template>
<client-only>
<div id="canvas" />
</client-only>
</template>
<script>
import { jsPlumb } from 'jsplumb'
export default {
mounted () {
if (process.client) {
console.log('MOUNTED - 2')
jsPlumb.ready(function () {
console.log('MOUNTED - 3')
})
}
}
}
</script>
I get the error:
ReferenceError
document is not defined
I tried many things which were mentioned but nothing seems to work.
Instead of using process.client I used the process.browser and it worked fine for me. Please refer the link: https://stackoverflow.com/a/69822954/7584240

defining global variables with vite development

Now I am using vite build tool for my vue SFC app. I read the documentation of vite with the link below:
vite config link
If I am not wrong, the define option in config could be used for defining global constants. What I want to do is to define for example the name of my App in a variable inside this option and then use it in my Vue components. But unfortunately there is no example of code in the documentation about this option.
I tried this code in my vite.config.js file:
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
define: {
global: {
appName: "my-custom-name"
}
},
plugins: [vue()]
})
I am not sure that the syntax and code is correct! And also if it is correct I don't know how to call (use) this constant in my vue app components (.vue files). For example I want to use it in template or script part of this component:
<template>
<div class="bgNow">
<p class="color1">
{{ use here }}
</p>
</template>
<script>
export default {
data() {
return {
name: use here
};
},
methods: {
nameMethod() {
console.log(use here);
}
} // end of method
} // end of export
</script>
<style scoped></style>
I declared the places that want with "use here" in the code. And also if there is any other way that I could define some global constants and variables in my vite vue app, I very much appreciate your help to tell me about that.
define is a config that tells Vite how to perform a search-and-replace. It can only replace one string for another (objects cannot be used as a replacement).
For example, to replace all instances of appName with "my-custom-name", use the following config. Note JSON.stringify() is used (per the recommendation in the docs) to ensure the literal string replacement is properly quoted.
export default defineConfig({
define: {
appName: JSON.stringify('my-custom-name')
}
})
If App.vue contained:
<script setup>
console.log('appName', appName)
</script>
It would be transformed to:
<script setup>
console.log("appName", "my-custom-name")
</script>
demo

Creating a simple VUE.JS application

I am trying to use a simple polygon cropper from Vue within an application by following the steps in this article.
I created my app using:
vue init webpack myproject
Now, I need to add the sample template to my app (it has a src folder), but I am not sure how to amend or add this piece of code to my application. The template should be as follows per the linked article:
// Global
import Vue from 'vue';
import VuePolygonCropper from 'vue-polygon-cropper';
Vue.component(VuePolygonCropper);
// Local
import VueCropper from 'vue-polygon-cropper';
export default {
components: { VueCropper}
}
<template>
<div id="app">
<polygon-crop :imageSource="'/demo.png'" ref="canvas"></polygon-crop>
<button #click.prevent="crop">Crop</button>
<button #click.prevent="undo">Undo</button>
<button #click.prevent="redo">Redo</button>
<button #click.prevent="reset">Reset</button>
</div>
</template>
<script>
export default {
name: 'App',
methods: {
crop: function () {
this.$refs.canvas.crop();
},
undo: function () {
this.$refs.canvas.undo();
},
redo: function () {
this.$refs.canvas.redo();
},
reset: function () {
this.$refs.canvas.reset();
}
}
};
</script>
I am not sure what the meaning of global or local is there. My src folder structure is as follows:
Directory of C:\ThermoAnalyser\vue_js\myproject\src
27/12/2020 11:37 AM <DIR> .
27/12/2020 11:37 AM <DIR> ..
27/12/2020 11:37 AM 374 App.vue
27/12/2020 11:37 AM <DIR> assets
27/12/2020 11:37 AM <DIR> components
27/12/2020 11:37 AM 360 main.js
27/12/2020 11:37 AM <DIR> router
2 File(s) 734 bytes
5 Dir(s) 301,183,393,792 bytes free
You won't be able to get this component running with just this code snippet, there's a couple of things that you would need to do to fix this up.
Before we go any deeper, I would like you to make sure if you have installed this vue-polygon-cropper component. If you navigated to the package.json that is located in the same level as your "src" folder, you would see a mention of vue-polygon-cropper there, if not please install it by npm install vue-polygon-croper .
Let's take a look at your <template> section first:
1- In the template, you call a component <polygon-crop> but, there is no component registered by that name in your script (What you are attempting to register is 'VuePolygonCropper' so you should try using <VuePolygonCropper> component instead.
2-I see there you copied and pasted the logo image in assets, that's a great way to test it! However, Digging through the creator's example that they put up on github, It seems like this component requires a full path to your image file instead of the relative path. so instead of /src/assets/logo.png try doing :imageSource="require('../assets/logo.png')"
I'm assuming the assets logo is on a folder that is one level above your current component.
So your template should look like this:
<template>
<div id="app">
<VuePolygonCropper :imageSource = "require('../assets/logo.png')"
ref="canvas"> </VuePolygonCropper>
<button #click.prevent="crop"> Crop </button>
<button #click.prevent="undo"> Undo </button>
<button #click.prevent="redo"> Redo </button>
<button #click.prevent="reset"> Reset </button>
</div>
</template>
Now on to your script!
just import the VuePolygonCropper and mention it as a component in the components section.
You don't need to import vue and do Vue.component(VuePolygonCropper). The correct way to register this component would be like this
<script>
import VuePolygonCropper from 'vue-polygon-cropper';
export
default
{
name: 'App',
components:{VuePolygonCropper},
methods: {
crop: function() {
this.$refs.canvas.crop();
},
undo: function()
{
this.$refs.canvas.undo();
},
redo: function()
{
this.$refs.canvas.redo();
},
reset: function()
{
this.$refs.canvas.reset();
}
}
};
</script>
For the heck of it, I have created a codesandbox that you can play around with . You can try to play around with the App.vue file and see how it was created.
Happy coding!
"Global" vs "Local"
The "global" and "local" comments refer to global component registration and local component registration. The article shows both ways of registering the vue-polygon-cropper component probably to make it easier to copy-paste into your own code.
Global component registration
You can register a component globally so that it could be used in another component without the consuming component having to register it locally. This is normally used for commonly used components that are frequently found in several components (e.g., a button).
Below is an example of global component registration that allows MyButton to be used in MyForm. Notice how MyForm's <template> uses MyButton without any component registration for MyButton in its <script>.
// main.js
import Vue from 'vue'
Vue.component('MyButton', { /*...*/ })
// MyForm.vue
<template>
<MyButton #click="onClick" />
</template>
<script>
export default {
methods: {
onClick() { /*...*/ }
}
}
</script>
Local component registration
For seldom used components (ones that are only found in a few components of your app), register the components locally instead to help minimize the bundle size if needed. If your component is never used (e.g., from a refactoring down the road), local registration allows the bundler to crop out your component from the final output.
Here's the previous example with local registration instead:
// MyButton.vue
<template>
<button />
</template>
// MyForm.vue
<template>
<MyButton #click="onClick" />
</template>
<script>
import MyButton from './MyButton.vue'
export default {
components: {
MyButton 👈
},
methods: {
onClick() { /*...*/ }
}
}
</script>
Getting started with the sample code
To quickly get the sample code working in your project:
Copy the <template> and <script> parts of the sample code into your src/App.vue, replacing everything.
In the App.vue's component definition, locally register vue-polygon-cropper as polygon-crop:
<script>
import VuePolygonCropper from 'vue-polygon-cropper'
export default {
components: {
'polygon-crop': VuePolygonCropper
}
}
<script>
The sample code refers to an image at /demo.png, but your sample app only has src/assets/logo.png, so edit src/App.vue's <template> so that polygon-crop uses src/assets/logo.png. We have to require the asset's path so that Webpack properly resolves the path from source:
<polygon-crop :imageSource="require('#/assets/logo.png')">
sample GitHub repo
Update to Vue CLI
Consider using Vue CLI's default generated templates (from vue create) instead of that outdated webpack template. The newly created project would still use Webpack, but most of the config for developer ergonomics are abstracted away, which can be helpful for beginners.
vue create myproject

Import npm package into a Vue.js Single File component

I would like to use Jodit in a SFC, but I am not sure how this is supposed to be done. I realized there is a wrapper (jodit-vue), but for educational purposes, I would like to know how it's done without it. I created a Vue CLI project with default presets, and all I changed is the App.vue:
<template>
<div id="app">
<textarea id="editor" name="editor"></textarea>
</div>
</template>
<script>
import "../node_modules/jodit/build/jodit.min.js"
export default {
name: 'App',
created(){
let editor = new Jodit('#editor');
editor.value = '<p>start</p>';
}
}
</script>
<style>
#import "../node_modules/jodit/build/jodit.min.css" ;
</style>
This produces the error: error 'Jodit' is not defined no-undef, and
if I change the import to:
import Jodit from "../node_modules/jodit/build/jodit.min.js"
Then the compilation is fine, but the browser console says:
vue.runtime.esm.js?2b0e:1888 TypeError: _node_modules_jodit_build_jodit_min_js__WEBPACK_IMPORTED_MODULE_0___default.a is not a constructor
Admittedly, I am new to all of this, but pointing me to the right direction is appreciated.
The jodit module exports the Jodit constructor, so your component would import it like this:
import { Jodit } from 'jodit'
You'd also need the Jodit styles, which could be imported like this:
import 'jodit/build/jodit.min.css'
To create a Jodit instance, we need to provide an element or selector to an existing <textarea>. The Vue component's elements are available in the mounted() lifecycle hook (not in the created() hook), so that's where we would initialize:
export default {
mounted() {
const editor = new Jodit('#editor')
editor.value = '<p>start</p>'
},
}
demo

TypeError: _vm.moment is not a function in Vuejs

I have a problem migrating to moment on Vuejs.
After running npm install vue-moment and adding to my script:
<script>
const moment = require('vue-moment');
...
</script>
I added this into my <template> :
<h1>{{moment('2017-12-20 11:00').fromNow()}}</h1>
And I get this error:
[Vue warn]: Error in render: "TypeError: _vm.moment is not a function"
You can use it globally as #red-X said, but you can add it only on your component:
import moment from 'moment'
export default {
data: () => ({
moment: moment
})
}
And then you can access it in your HTML template.
But i recommand you to use computed vars for using this kind of code, and to not have logic in your html template, just render computed vars inside your templates for readability.
And with this solution, you don't need to have moment library available globally or in your component, just the import.
Here it's an example :
import moment from 'moment'
export default {
computed: {
distanceFromNow() {
return moment('2017-12-20 11:00').fromNow()
}
}
}
And in your template :
<template>
<div>
{{ distanceFromNow }}
</div>
</template>
import * as momentTemp from 'moment';
const moment = momentTemp["default"];
Did you add the 'moment' attribute to the lifecycle 'methods',forExample:
methods:{
moment,
function a(){},
}
Did you add moment to the global Vue object like this:
const moment = require('vue-moment');
Vue.use(moment)
Just adding it to the local scope of a component will not make it available for use in the template. Everything referenced in the template is taken from the component itself.