Categories
Vue

Developing Vue Apps with Class-Based Components — TypeScript, Superclasses, Hooks, and Mixins

Spread the love

If we prefer to use classes, we can use the class-based components API that comes with Vue.

In this article, we’ll look at how to developing Vue apps with class-based components.

TypeScript, Superclasses, and Mixins

We can add props and inherit superclass components with the mixins method in our Vue TypeScript project.

For instance, we can write:

<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component, { mixins } from "vue-class-component";

const GreetingProps = Vue.extend({
  props: {
    name: String,
  },
});

@Component
class Super extends Vue {
  lastName = "smith";
}

@Component
export default class HelloWorld extends mixins(GreetingProps, Super) {
  get message(): string {
    return `Hello, ${this.name} ${this.lastName}`;
  }
}
</script>

We create the Super component class with the 1astName property.

And we have the GreetProps class that we create with the Vue.extend method so we can accept props in a way that’s acceptable by TypeScript.

Then we call the mixins method with the GreetProps and Super methods so we can inherit from both classes.

We inherit from both classes, so this.name is 'james' and this.lastName is 'smith' .

We can define properties with type definitions.

For instance, we can write:

<template>
  <div>
    <p v-for="p of persons" :key="p">{{ p.firstName }} {{ p.lastName }}</p>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";

interface Person {
  firstName: string;
  lastName: string;
}

@Component
export default class HelloWorld extends Vue {
  persons!: Person[] = [
    { firstName: "james", lastName: "smith" },
    { firstName: "jane", lastName: "doe" },
  ];
}
</script>

We create the Person interface and use that for defining the type of the persons class property.

The ! means the class property isn’t nullable.

Now if the persons array entries have extra properties, we’ll get an error from the TypeScript compiler.

Refs and TypeScript

To define and assign refs with TypeScript class-based Vue components, we write:

<template>
  <div>
    <input ref="input" />
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";

@Component
export default class HelloWorld extends Vue {
  $refs!: {
    input: HTMLInputElement;
  };

  mounted() {
    this.$refs.input.focus();
  }
}
</script>

We have to set the type for each $refs property we assign.

input is an HTML input element, so we set it to the HTMLInputElement type.

Then we call call focus on it to focus it.

With the type annotation added, we get autocomplete when we type in the code in the mounted hook.

Hooks Autocomplete

To add autocomplete for hooks, we write:

main.ts

import Vue from "vue";
import App from "./App.vue";
import "vue-class-component/hooks";
Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App)
}).$mount("#app");

App.vue

<template>
  <div id="app">
    <HelloWorld />
  </div>
</template>

<script lang='ts'>
import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
  components: {
    HelloWorld,
  },
};
</script>

components/HelloWorld.vue

<template>
  <div>
    {{ message }}
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";

@Component
export default class HelloWorld extends Vue {
  data() {
    return {
      message: "hello world",
    };
  }
}
</script>

Once we add:

import "vue-class-component/hooks";

in main.ts , we get autocomplete when we type in data in the HelloWorld component.

Conclusion

We can add hooks autocomplete, mixins and superclass inheritance, and refs type annotation within our Vue class-based components written in TypeScript.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *