VueJS extend component for customization - vue.js

Is there any way to use some Generic component and keep it's props emitters etc and just customize it?
Example:
<template>
<GenericComponent color="black">
Something in the default slot
</GenericComponent>
</template>
<script>
import GenericComponent from 'GenericComponent'
export default {
name: 'MyCustomizedComponent'
props: // to take same props as GenericComponent and pass it to GenericCompnent?
// and it emits all events from GenericComponent
// I could probably just copy props and pass it directly to GenericComponent, but what if there
// is many
}
</script>
<style scoped>
//some changes to Generic component
<style>
So I could just create props, and define all # from GenericComponent and emit them same way, but is there any easy way to do it ?

You can either use mixins, to reuse code across several components.
You can also create a wrapper component to the original component, do your customizations, and use v-bind="$props" to propagate all props to the original component and v-on="$listeners" to emit all events from the original component to the parent.
I'm not sure what is best for your case.

Related

How to make a Base component that will allow other components to inherit new functionality or code from it in Vue JS

Component 1:-
<template>
<blur :isData="isData">
<!-- logic/implementation of component 1 -->
<div>
</div>
</blur>
<template>
<script>
import blur from "../shared/Blur";
name: "component-1",
components: {
blur,
},
</script>
Just like this component1.vue, I have multiple components which are using blur component. Is it possible that instead of writing and importing blur in every single component, I can make some base class that can transfer the blur functionality in every single component in the folder. Can something like this be achieved in vue ?
With Vue.component you can create globally registered components:
Vue.component('my-component-name', {
// ... options ...
})
Find out more here

Can you access Vue component lifecycle hooks externally?

I am using a component library within my web app and I'd like to attach functionality to one of the provided components.
So let's say I have a .vue file
<template>
<div>
... some stuff
<LibraryComponent />
</div>
</template>
<script>
import LibraryComponent from 'library'
export default {
components: {
LibraryComponent
}
}
</script>
I would love to be able to reach into the LibraryComponent and attach a method to the mounted hook from the parent. I figure I can update the code of the component itself in node_modules but that seems like a bad solution if the package gets updated.
Vue’s lifecycle hooks emit their own custom events.
Take a look at this article:
Vue.js Component Hooks as Events

pass router params to component object

I have view and I want to load svg based on router params, I have installed vue-loader and it is working if I hard code it.
<template>
<div>
<suit/>
</div>
</template>
<script>
export default {
components:{
suit: ()=>import('../assets/svg/'+Param+'.svg')
}
}
</script>
<style>
</style>
This is what I have. Instead of Param I want to get this.route.params, but when I try this I get undefined which is logical because components wrapper is object. Is there a way to pass a variable here or must I redo the whole thing?
Instead of this.route.params, within a component you should be using this.$route.params. Vue Router Docs.

Passing data from template to component

I have the following, which for my understanding should pass the value of html attribute to the #Prop with the same name however my console.log is always undefined. How is this accomplished?
import Vue from 'vue';
import { Component, Prop } from 'vue-property-decorator';
#Component({})
export default class RelayComponent extends Vue {
#Prop([String]) service: string;
constructor() {
super();
console.log(this.service);
...
HTML
<template>
<div service="expecting this value passed"></div>
</template>
<script src="./relay.ts"></script>
Vue props
Vue props are intended to pass data from a parent vue component or instance to a child vue component.
So you have a vue component, you set up a #Prop and then you get the prop for the html of the parent. Should you have a my-parent and my-child components, the my-parent template could be:
<template>
<my-child count="7"></my-child>
</template>
So a child component like this:
<template>
<div class="counter">{{count}}</div>
</template>
<script lang="ts">
import Vue from 'vue';
import { Component, Prop } from 'vue-property-decorator';
#Component({})
export default class myChild extends Vue {
#Prop() count: number;
}
</script>
Would get 7 as its count prop.
Now, in your case, there is only one component, and you're trying to setup the service variable of the component from the HTML. This is sort of weird because the point of Vue is to achieve declarative rendering from the component data: is the HTML who reacts to data changes, not your component who gets data from the HTML.
(Of course, you can also setup v-model and event listeners to make your components react to user input, but that's another story).
Basically, if I understood correctly what you want to do, your issue is that you're trying to get the service prop from the HTML of the very RelayComponent component.
Instead, you should setup the service prop in the component parent:
// Code of some parent component that renders the RelayComponent
<template>
<relay-component service="this would set the service prop as a string"></relay-component>
</template>
Only, when dealing with objects, you usually don't pass down a plain string, but a javascript object, and a service variable probably is an object, so changes are you're behind something like this:
<template>
<relay-component v-bind:service="serviceVariableInTheParentComponent"></relay-component>
</template>
Where the parent component has a service variable in its data.
 Constructor and lifehooks
Be wary about explicitly calling constructor in vue class components. If you modify the component state in the constructor, you can break the component.
Probably, you should consider to ever use the created() lifecycle hook instead of constructor() in every Vue component.

Sub-class a vue component

I have some repeating functionality that many components will use. So my first thought is I should create a base component and have my components inherit/subclass from this.
But maybe this is not possible in vue.js and maybe its not the vue.js way to do things? If I explain my use-case can you suggest how best I implement this in vue.js?
BasePage.vue
<template>
...
</template>
<script>
export default {
name: 'animated-page',
watch: {
'$route' (to, from) {
// conditionally choose animations depending on route
const toDepth = to.path.split('/').length
const fromDepth = from.path.split('/').length
this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
}
}
}
</script>
<style>
... my animations
</style>
About.vue
<template>
...
</template>
<script>
export default {
// somehow inherit from BasePage
name: 'about-page',
... 'about' specific code
}
</script>
<style>
</style>
You can use extend to subclass the Vue constructor, and you can use it on components to subclass them.
In general, though, you should prefer composition to inheritance and use mixins where you can.
Mixins are a flexible way to distribute reusable functionalities for Vue components. A mixin object can contain any component options. When a component uses a mixin, all options in the mixin will be “mixed” into the component’s own options.