How to extend a component in Vue 3? - vue.js

The import is working just fine in case I try to use the component from element-plus directly.
What I'm trying to do though, is to extend a component from element-plus library (it uses the composition api from Vue 3) and add some additional properties to my component and methods.
In Vue 2 it would look something like this:
export default {
extends: SomeComponent
}
In Vue 3 this seems to not be working anymore.
I've read about defineComponent but so far, without success implementing it.
Can someone shed me some lights? Thanks.

In order to extend a component that uses Composition API whereas another still uses Options API, we need to also do the setup, such as:
export default { extends: SomeComponent, setup: SomeComponent.setup }

Related

Gridsome: How to add Vue.use(MyPlugin) for a single page only?

I have added ReCaptcha plugin using Vue.use(ReCaptcha, {some options}) in Gridsome main.js which is displaying on all pages.
How to add plugin for a particular page only in gridsome?
I've never used ReCaptcha or Gridsome before, but generally, if you install a plugin using npm, then the simplest way to use it on a single page would be to import the plugin to the specific component rendered on the route you want to use it on. i.e
/* === MyComponent.vue === */
<script>
import plugin from 'packageName';
// or
import { pluginExport } from 'packageName';
export Default{
// You can then use the plugin/pluginExport here
}
From there you should be able to use the package in that specific component as you normally would if you implemented it app-wide with Vue.use. In some cases, depending on how the plugin is meant to be used, you may need to register the imported plugin Module as a child component in the components object. Like this vuejs QR Code generator for example.

How to lazy load a plugin in Vue?

Vue plugins usually requires a global setup in app entrypoint by Vue.use(somePlugin). Doing so increases the bundle size for all pages, which is often bad and that it is better to defer the downloading of the module until when the module is actually being used, aka lazy loading or code spliting.
How do I lazy load a plugin if only one page in my Vue app needs it?
To answer the OP's question more directly: You can't lazy load a plugin.
According to the documentation, plugins by definition provide globally-accessible functionality and must be setup with Vue.use() before the Vue instance is created. Due to this, they'll always be bundled with the entire Vue instance (in a vendors chunk, for example).
What you want is to lazy load the functionality in a smaller scope, at a component level. Depending on the plugin, the plugin module should also support some sort of direct code importing at a component level, like this one does. Because it just uses import statements, they can be async loaded.
TL;DR: Anything using Vue.use() can't be lazy loaded. Async imports can.
One of the options is to call your plugin file in created/mounted hook and do the stuff you want.
Just import it on the specific page an example would be "Slide" from "vue-burger-menu"
<script>
import { Slide } from "vue-burger-menu"
export default {
components: {
Slide
}
}
</script>

How to access a constant in main.js in another js file in vue.js framework?

I have a vue.js application and in the main.js file I have configured the Vuei18n as per the documentation. This is working perfectly and in order to access this in other components, I have added this to new Vue() instance and this is now accessible (with this.$i18n).
Now I have created a validator.js file for validation rules and I need to use the this.$i18n there, but its not working. I have also tried Vue.prototype.$i18n but that too not working. Can someone help me to find out where I went wrong ?
 exporting the i18n variable
I'll assume your app is a vue-cli app, or at least that you use webpack to build it
and therefore can use ES modules.
Working with vue-i18n you would do something like the following:
// step 1: define the i18n object via new Vue18n
const i18n = new VueI18n({
locale: DEFAULT_LANGUAGE,
messages,
});
// step 2: setup the Vue object to use this object:
new Vue({
i18n,
... store, router.... whatever
})
Where messages contain all the JSON's with the translations keys and values.
I guess you already are doing something like this.
And now, in your validator module you need the very same i18n object you plugged to Vue.
Instead of trying to get to Vue in your validator, you can just plain export the i18n varible from main.js:
export {i18n}
So, in your validator.js file, you can just import it:
import {i18n} from '#/main.js' // or whatever is the path
This is pretty much how I'm solving the validator internationalization problem in my own application.
Important note: circular dependencies
If you're already importing the validator.js in your main.js, you won't be able to import i18n from main in your validator module. To avoid such a problem, you would move the i18n initialization and exportation to another module, such as i18n.js, so the validator and the main file can import it independently. 
 Without es6 modules
In case you're not using webpack or another bundler to bundle your code, you can still just export the i18n object to the window object:
window.i18n = i18n
and then use it from whatever file. You just need to be careful to store the i18n object in window before any file will try to access it.
I think what you're looking for is Custom Events. According to this documentation, you should be able to emit your variable with something like below
this.$emit('send-i18n', this.$i18n)
Still according to the documentation, try to use v-on:send-i18n to retreive your value.
Hope it works.

How i can register component globally and define default behavior?

It is possible, register component and define default behavior?
import Vue from 'vue'
import SmartSelect from '~/components/lib/smart_controls/inputs/SmartSelect'
Vue.component('smart-select', { onerror: Vue.myMethod($event), ...SmartSelect })
if you’re using Webpack (or Vue CLI 3+, which uses Webpack
internally), you can use require.context to globally register only
these very common base components
https://v2.vuejs.org/v2/guide/components-registration.html#Automatic-Global-Registration-of-Base-Components
define your default behavior inside your SmartSelect component.
if your meaning was to define a default behavior to all vue components, than you should read more about vue inheritance, which is a way to declare a base component with defaut behavior, and make other components to inherit and override that behavior. here's a good place to start

v-form and v-text-field not working in vue cli 3.0

I'm currently creating a project using Vue Cli 3. And for its UI, I chose to use Vuetify. In adding Vuetify to Vue Cli 3, I simply ran the command
vue add vuetify
I can use other features of Vuetify like v-layout, v-button, etc. But whenever I'm using v-form or v-text-field, it seems to be not working. And the error is:
[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option
Can someone help me so I can make these things work? Thank you in advance!
This happened to me too. It seems like an importation problem. I solved it importing vuetify css file at my main.js file. Like:
import 'vuetify/dist/vuetify.min.css';
Did you choose "Use a-la-carte components" during the installation process of vue-cli-plugin-vuetify? If so, make sure that you also have imported and added all necessary components to the configuration file plugins/vuetify.js
Add the names of your needed components to the import statement.
import {
Vuetify,
VApp,
...,
VForm,
VTextField,
...
} from 'vuetify';
And make sure you also add your imported components to the components section where vuetify gets initalized.
Vue.use(Vuetify,{
components: {
VApp,
...,
VForm
VTextField,
...
}})
Further information: https://vuetifyjs.com/en/guides/a-la-carte