-
-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Description
What problem does this feature solve?
I just discovered that we could use ES6 class for creating components instead of the Composition API setup function. The best thing is it works out of the box in Vue 3 without any dependency on vue-class-component
or other libraries! Even the experimental template interpolation service in Vetur is working flawlessly with it!!!
Surprisingly I couldn't find this way of creating components in any of Vue 3 documentation. Not sure why, or am I missing something!?
With official support, we could make the experience even better.
Why use ES6 class:
In the current way of creating a component using setup function & composition API, users are encouraged to create closure functions. When the number of instances of a component is minimal this doesn't make much difference. But when there are so many instances of the component, multiples of those many functions objects would be created, which doesn't look ideal.
For instance, 1000 instances of the following component would create 1000 getUserRepositories
function objects. Which is overkill.
import { fetchUserRepositories } from '@/api/repositories'
setup (props) {
let repositories = []
const getUserRepositories = async () => {
repositories = await fetchUserRepositories(props.user)
}
return {
repositories,
getUserRepositories
}
}
What does the proposed API look like?
This is how we could create a Counter component using ES6 class & composition API. And it works with the current release of Vue 3!
<template>
<div class="counter">
Counter: {{ valueInternal }}<br />
<button type="button" @click="onAdd">Add</button>
<button type="button" @click="onSubtract">Sub</button>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, Ref } from "vue";
class Counter {
valueInternal: Ref<number>;
constructor(val: number) {
this.valueInternal = ref(val);
// Guess following binding & convertion to own properties are needed because of hasOwn check @ https://github.com/vuejs/vue-next/blob/master/packages/runtime-core/src/componentPublicInstance.ts#L293
// We must be able to remove it with official support
this.onAdd = this.onAdd.bind(this);
this.onSubtract = this.onSubtract.bind(this);
}
onAdd() {
this.valueInternal.value++;
}
onSubtract() {
this.valueInternal.value--;
}
someOtherMethod() {
// Statements
}
}
export default defineComponent({
props: {
value: Number
},
setup: props => new Counter(props.value || 0)
});
</script>
I have committed a dummy project with working example @ https://github.com/sreenaths/vue3-composition-class
What could we do through official support:
There could be more, but the following are some of the items that came to my mind.
- Direct default export of the class from inside the script tag.
export default Counter
instead of this working snippetexport default defineComponent(props => new Counter(props));
. - Some way to bypass hasOwn check explained above in Counter constructor so that inherited properties can be accessed from inside the template - Can we use decorators for that?
- Should we have an interface for type-checking?
- When directly exporting the Class, can we provide some way to pass props definition?
- Documentation.