Home Web Development Vue.js 3 Cookbook

Vue.js 3 Cookbook

By Heitor Ramon Ribeiro
books-svg-icon Book
eBook $35.99 $24.99
Print $48.99
Subscription $15.99 $10 p/m for three months
$10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
BUY NOW $10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
eBook $35.99 $24.99
Print $48.99
Subscription $15.99 $10 p/m for three months
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
  1. Free Chapter
    Introducing TypeScript and the Vue Ecosystem
About this book
Vue.js is a progressive web framework for building professional user interfaces for your web applications. With Vue.js 3, the frontend framework is reinforced with architectural enhancements, new base languages, new render processes, and separated core components. The book starts with recipes for implementing Vue.js 3’s new features in your web development projects and migrating your existing Vue.js apps to the latest version. You will get up and running with TypeScript with Vue.js and find succinct solutions to common challenges and pitfalls faced in implementing components, derivatives, and animation, through to building plugins, adding state management, routing, and developing complete single-page applications (SPAs). As you advance, you'll discover recipes to help you integrate Vue.js apps with Nuxt.js in order to add server-side rendering capabilities to your SPAs. You'll then learn about the Vue.js ecosystem by exploring modern frameworks such as Quasar, Nuxt.js, Vuex, and Vuetify in your web projects. Finally, the book provides you with solutions for packaging and deploying your Vue.js apps. By the end of this Vue.js book, you'll be able to identify and solve challenges faced in building Vue.js applications and be able to adopt the Vue.js framework for frontend web projects of any scale.
Publication date:
September 2020
Publisher
Packt
Pages
562
ISBN
9781838826222

 
Introducing TypeScript and the Vue Ecosystem

TypeScript is a new Vue-based language, fully supported on Vue 3. It is now possible to use typed JSX (also know as TSX), type annotation, static verification of the code, and much more.

The Vue ecosystem is getting bigger each day, so to help us, the Vue team has developed some tools to improve project handling and management. Those tools are Vue CLI and Vue UI, which today are the main tools for local Vue development.

The Vue CLI tool is the beginning of every project; with it, you will be able to select the basic features or just a preset you had made, to create a new Vue project. After a project is created, you can use Vue UI to manage the project, add new features, check the status of the project, and do almost everything you previously needed to do in the command-line interface (CLI), with the addition of more features.

In these chapters, you learn more about TypeScript as a superset on JavaScript and how to use the power of the Vue CLI tool and Vue UI together to get a whole application up and running.

In this chapter, we'll cover the following recipes:

  • Creating a TypeScript project
  • Understanding TypeScript
  • Creating your first TypeScript class
  • Creating your first project with Vue CLI
  • Adding plugins to a Vue CLI project with Vue UI
  • Adding TypeScript to a Vue CLI project
  • Creating your first TypeScript Vue component with vue-class-component
  • Creating a custom mixin with vue-class-component
  • Creating a custom function decorator with vue-class-component
  • Adding custom hooks to vue-class-component
  • Adding vue-property-decorator to vue-class-component
 

Technical requirements

In this chapter, we will be using Node.js, Vue CLI, and TypeScript.

Attention, Windows users—you need to install an npm package called windows-build-tools to be able to install the following required packages. To do it, open PowerShell as administrator and execute the following command:
> npm install -g windows-build-tools.

To install the Vue CLI tool, open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:

> npm install -g @vue/cli @vue/cli-service-global

To install TypeScript, open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:

> npm install -g typescript
 

Creating a TypeScript project

TypeScript is a typed superset of JavaScript that, when compiled, gives us plain JavaScript code. It seems like a new language, but in the end, it's still JavaScript.

What is the advantage of using TypeScript? The main advantage is the typed syntax, which helps with static checking and code refactoring. You can still use all the JavaScript libraries and program with the latest ECMAScript features out of the box.

When compiled, TypeScript will deliver a pure JavaScript file that can run on any browser, Node.js, or any JavaScript engine that is capable of executing ECMAScript 3 or newer versions.

 

Getting ready

To start our project, we will need to create an npm project. Open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:

> npm init -y

You also need to install TypeScript, so open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:

> npm install typescript --only=dev
 

How to do it...

With our environment ready, we will need to start our TypeScript project. Let's create a .ts file and compile it:

  1. To start our TypeScript project, open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:
> tsc --init

This will create a tsconfig.json file inside our folder. This is a compiler settings file. Here, you can define the target, which JavaScript libraries will be available on the development, the target ECMAScript version, the module generation, and much more.

When developing for the web, don't forget to add the Document Object Model (DOM) to the libraries on the compilerOption property inside the tsconfig.json file so that you can have access to the window and document object when developing.
  1. Now, we need to create our index.ts file. Let's create some simple code inside the index.ts file that will log a math calculation in your terminal:
function sum(a: number, b: number): number {
return a + b;
}

const firstNumber: number = 10;

const secondNumber: number = 20;

console.log(sum(firstNumber, secondNumber));

This function receives two parameters, a and b, which both have their type set to number, and the function is expected to return a number. We made two variables, firstNumber and secondNumber, which in this case are both set to a number type—10 and 20 respectively—so, it's valid to pass to the function. If we had set it to any other type such as a string, Boolean, float, or an array, the compiler would have thrown an error about the static type checking on the variable and the function execution.

  1. Now, we need to compile this code to a JavaScript file. Open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:
> tsc ./index.ts

After the compilation, we can see the final file in index.js. If we look inside the file, the final code will be similar to this:

function sum(a, b) {
return a + b;
}
var firstNumber = 10;
var secondNumber = 20;
console.log(sum(firstNumber, secondNumber));

You may be wondering: where are my types? As ECMAScript is a dynamic language, the types of TypeScript exist only at the superset level, and won't be passed down to the JavaScript file.

Your final JavaScript will be in the form of a transpiled file, with the configurations defined in the tsconfig.json file.

 

How it works...

When we create our TypeScript project, a file named tsconfig.json is created inside our folder. This file coordinates all the rules on the compiler and the static type checking during the development process. All developments are based on the rules defined in this file. Each environment depends on specific rules and libraries that need to be imported.

When developing, we can assign types directly to constants, variables, function parameters, returns, and much more. These types of definitions can prevent basic type errors and code refactoring.

After the development is done and we compile the project, the final product will be a pure JavaScript file. This file won't have any type of checking, due to the dynamic type of JavaScript.

This JavaScript file gets transpiled to the target model and defined on the configuration file, so we can execute it without any problems.

 

See also

 

Understanding TypeScript

TypeScript is a type-based language. Much of its power comes with the ability to use static code analysis with JavaScript. This is possible thanks to the tools that exist inside the TypeScript environment.

These tools include the compiler, which can provide static analysis during development and after compilation, and the ECMAScript transpiler, which can make your code available to run on almost any JavaScript engine.

Let's get to know more about the language, and how it works.

 

Getting ready

To start, we will need to create an npm project. Open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:

> npm init -y

You also need to install TypeScript, so open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:

> npm install typescript --only=dev
 

Types

The main feature we get from using TypeScript is the types. In this section, we will learn about types, how to declare them, and how to use them.

These are some of the basic types in a statically typed language:

  • String
  • Number
  • Boolean
  • Arrays
  • Tuple
  • Enum
  • Any
  • Void
  • Objects

Let's talk about some of these types and show how they can be used in TypeScript.

 

String

All the textual data on JavaScript will be treated as a string. To declare a string, we always need to surround it with double (") or single (') quotes, or the (`) grave accent, commonly known as a template string.

Declaring template strings inside text is not a problem with TypeScript. Template strings are a feature in ECMAScript that made it possible to add a variable inside a string without the need for concatenation:

const myText: string = 'My Simple Text';
const myTextAgain: string = "My Simple Text";
const greeting: string = `Welcome back ${myName}!`;
 

Number

In JavaScript, all numbers are floating-point values. In TypeScript, it's the same. Those numbers get a number type. In addition to the hexadecimal and decimal numbers, the binary and octal literals that were introduced in ECMAScript 2015 are treated like numbers too:

const myAge: number = 31;
const hexNumber: number = 0xf010d;
const binaryNumber: number = 0b1011;
const octalNumber: number = 0o744;
 

Boolean

The most basic type in the programming languages is the boolean values—a simple 1 or 0, and true or false. This is called a boolean:

const isTaskDone: boolean = false;
const isGreaterThen: boolean = 10 > 5;
 

Arrays

A group of elements in most of the languages is commonly called an array. In TypeScript, we can declare it in two different ways.

The most simple way is just to declare the type of the element followed by [] (square brackets) to denote that it is an array of the declared type:

const primeNumbers: number[] = [1, 3, 5, 7, 11];

Or, you can declare generically, using the Array<type> declaration. This is not the most common way used, but, depending on the code you are developing, you may need to use it:

const switchInstructions: Array<boolean> = [true, false, false, true];
 

Tuple

Tuples are a type of variable that has a specific structure. Structurally, a tuple is an array of two elements; both are a known type by the compiler and the user, but those elements don't need to have the same type:

let person: [string, number];
person = ['Heitor', 31];

console.log(`My name is ${person[0]} and I am ${person[1]} years old`);

If you try to access an element outside of the known indices, you will get an error.

 

Enum

Enums are similar to JavaScript objects, but they have some special attributes that help in the development of your application. You can have a friendly name for numeric values or a more controlled environment for the constants on the variables a function can accept.

A numeric enum can be created without any declaration. By doing this, it will start with the initial values of 0 and finish with the value of the final index number; or, you can get the name of the enum, passing the index of the enum value:

enum ErrorLevel { 
Info,
Debug,
Warning,
Error,
Critical,
}

console.log(ErrorLevel.Error); // 3
console.log(ErrorLevel[3]); // Error

Or, an enum can be declared with values. It can be an initial declaration that the TypeScript compiler will interpret the rest of the elements as an increment of the first one, or an individual declaration:

enum Color {
Red = '#FF0000',
Blue = '#0000FF',
Green = '#00FF00',
}

enum Languages {
JavaScript = 1,
PHP,
Python,
Java = 10,
Ruby,
Rust,
TypeScript,
}

console.log(Color.Red) // '#FF0000'
console.log(Languages.TypeScript) // 13
 

Any

As JavaScript is a dynamic language, TypeScript needed to implement a type that has no defined value, so it implemented the any type. The most used case for the any type any is when using values that came from a third-party library. In that case, we know that we are dropping the type checking:

let maybeIs: any = 4;
maybeIs = 'a string?';
maybeIs = true;

The main use of the any type is when you are upgrading a legacy JavaScript project to TypeScript, and you can gradually add the types and validations to the variables and functions.

 

Void

As the opposite of any, void is the absence of the type at all. The most used case is with functions that won't return any values:

function logThis(str: string): void{
console.log(str);
}

Using void to type a variable is useless because it only can be assigned to undefined and null.

 

Objects

An object in TypeScripts has a special form of declaring because it can be declared as an interface, as a direct object, or as a type of its own.

Declaring an object as an interface, you have to declare the interface before using it, all the attributes must be passed, and the types need to be set:

interface IPerson {
name: string;
age: number;
}

const person: IPerson = {
name: 'Heitor',
age: 31,
};

Using objects as direct inputs is sometimes common when passing to a function:

function greetingUser(user: {name: string, lastName: string}) {
console.log(`Hello, ${user.name} ${user.lastName}`);
}

And finally, they are used for declaring a type of object and reusing it:

type Person = {
name: string,
age: number,
};

const person: Person = {
name: 'Heitor',
age: 31,
};

console.log(`My name is ${person.name}, I am ${person.age} years old`);
 

Functions

In TypeScript, one of the most difficult types to declare is a function. It can get very complex in a just simple concatenation of the functional chain.

Declaring a function in TypeScript is a composition of the parameters that the function will receive and the final type that the function will return.

You can declare a simple function inside a constant, like this:

const sumOfValues: (a:number, b:number): number = (a: number, b: number): number => a + b;

A more complex function declared inside a constant can be declared like this:

const complexFunction: (a: number) => (b:number) => number = (a: number): (b: number) => number => (b: number): number => a + b;

When declaring a function as a normal function, the way to type it is almost the same as in a constant way, but you don't need to declare that the functions are a function. Here is an example:

function foo(a: number, b:number): number{
return a + b;
}
 

Interfaces

TypeScript checks that the values of variables are the correct type and the same principle is applied to classes, objects, or contracts between your code. This is commonly known as "duck typing" or "structural sub-typing". Interfaces exist to fill this space and define these contracts or types.

Let's try to understand an interface with this example:

function greetingStudent(student: {name: string}){
console.log(`Hello ${student.name}`);
}

const newStudent = {name: 'Heitor'};

greetingStudent(newStudent);

The function will know that the object has the property name on it and that it's valid to call it.

We can rewrite it with the interface type for better code management:

interface IStudent {
name: string;
course?: string;
readonly university: string;
}

function greetingStudent(student: IStudent){
console.log(`Hello ${student.name}`);
if(student.course){
console.log(`Welcome to the ${student.course}` semester`);
}
}

const newStudent: IStudent = { name: 'Heitor', university: 'UDF' };

greetingStudent(newStudent);

As you can see, we have a new property called course that has a ? declared on it. This symbolizes that this property can be nulled or undefined. It's called an optional property.

There is a property with a read-only attribute declared. If we try to change after it's declared on the variable creation, we will receive a compile error because it makes the property read-only.

 

Decorators

A new feature was introduced in ECMAScript 6—classes. With the introduction of these, the usage of decorators was made possible on the JavaScript engine.

Decorators provide a way to add both annotations and meta-programming syntax to class declarations and its members. As it's in a final state of approval on the TC-39 committee (where TC stands for Technical Committee), the TypeScript compiler already has this available to be used.

To enable it, you can set the flags on the tsconfig.json file:

{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true
}
}

Decorators are a special kind of declaration that can be attached to a class, method, accessor property, or parameter. They are used in the form of @expression, where the expression is a function that will be called at runtime.

An example of a decorator that can be applied to a class can be seen in the following code snippet:

function classSeal(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}

When you create this function, you are saying that the object of the constructor and the prototype of it will be sealed.

To use it inside a class is very simple:

@classSeal
class Animal {
sound: string;
constructor(sound: string) {
this.sound = sound;
}
emitSound() {
return "The animal says, " + this.sound;
}
}

These are just some examples of decorators and their powers to help you with the development of object-oriented programming (OOP) with TypeScript.

 

In conclusion

In summary, types are just a way to make our life easier in the process of development with TypeScript and JavaScript.

Because JavaScript is a dynamic language and doesn't have a static type, all the types and interfaces declared in TypeScript are strictly used just by TypeScript. This helps the compiler catch errors, warnings, and the language server to help the integrated development environment (IDE) on the development process to analyze your code as it is being written.

This is a basic introduction to TypeScript, covering the basics of the typed language, and how to understand and use it. There is much more to learn about its use, such as generics, modules, namespaces, and so on.

With this introduction, you can understand how the new Vue 3 core works and how to use the basics of TypeScript in your project, and take advantage of the typed language on your project.

There is always more knowledge to find on TypeScript, as it is a growing "language" on top of JavaScript and has a growing community.

Don't forget to look at the TypeScript documentation to find out more about it and how it can improve your code from now on.

 

See also

You can find more information about TypeScript basic types at https://www.typescriptlang.org/docs/handbook/basic-types.html.

You can find more information about TypeScript functions at https://www.typescriptlang.org/docs/handbook/functions.html.

You can find more information about TypeScript enums at https://www.typescriptlang.org/docs/handbook/enums.html.

You can find more information about TypeScript advanced types at https://www.typescriptlang.org/docs/handbook/advanced-types.html.

You can find more information about TypeScript decorators at https://www.typescriptlang.org/docs/handbook/decorators.html.

View a cheatsheet on TypeScript types at https://rmolinamir.github.io/typescript-cheatsheet/#types.

 

Creating your first TypeScript class

In TypeScript, there is no main paradigm in which you write your program. You can choose between object-oriented, structural, or event functional.

In most cases, you will see an OOP paradigm being used. In this recipe, we will learn about creating a class inside TypeScript, its inheritance, the interface, and other properties that can be used inside the code.

 

Getting ready

To start our project, we will need to create an npm project. To do this, open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:

> npm init -y

You also need to install TypeScript. To do this, open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:

> npm install typescript --only=dev
 

How to do it...

When writing a class inside a TypeScript file, we first need to have in mind what this class will do, what this class can be for, how it can be extended by another class through inheritance, and how it can be affected in the process.

Imagine that we have a basic Animal class. This class can have some basic properties such as its name, whether it produces a sound, its family, and the basic food chain this animal eats.

  1. Let's start with the basics of the process, the food chain. We need to make sure that it's an innumerable list, and that each file that is using it will have the same value at the end. We just need to call a constant variable:
export enum FoodChainType {
Carnivorous = 'carnivorous',
Herbivorous = 'herbivorous',
Omnivorous = 'omnivorous',
}
  1. Now, we want to make the basic interface for our animal. We know that our animal has a name, can produce a sound, can be part of a family, and be in a food chain category. Using an interface in a class, we make a contract between the class and what will be exposed, helping in the development process:
interface IAnimal {
name: string;
sound?: string;
family: string;
foodChainType: FoodChainType;
}
  1. With all that settled, we can make our Animal class. Each class can have its constructor. The class constructor can be simple, containing just some variables as arguments, or can be more complex and have an object as an argument. If your constructor will have any parameters, an interface or declaring the type of each parameter is needed. In this case, our constructor will be an object and will have only one parameter that is the same as the Animal, so it will extend the IAnimal interface:
interface IAnimalConstructor extends IAnimal { 
}
  1. Now, to make our class, we have declared the interfaces and enums that will be used. We will start by declaring that the class will implement the IBasicAnimal interface. To do this, we need to add some public elements that our class will have and declare those too. We will need to implement the functions to show what animal it is and what sound it makes. Now, we have a basic class that includes all the attributes for our animal. It has separate interfaces for the class and the constructors. The enum for the food chain is declared in a human-readable way, so the JavaScript imports of this library can execute without any problems:
interface IBasicAnimal extends IAnimal {
whoAmI: () => void;
makeSound: () => void;
}

export class Animal implements IBasicAnimal {
public name: string;
public sound: string;
public family: string;
public foodChainType: FoodChainType;

constructor(params: IAnimalConstructor) {
this.name = params.name;
this.sound = params.sound || '';
this.family = params.family;
this.foodChainType = params.foodChainType;
}

public whoAmI(): void {
console.log(`I am a ${this.name}, my family is ${this.family}.
My diet is ${this.foodChainType}.`);
if (this.sound) {
console.log([...Array(2).fill(this.sound)].join(', '));
}
}

public makeSound(): void {
console.log(this.sound);
}
}
  1. Let's extend this class with a few lines of code and transform this Animal into a Dog:
import {Animal, FoodChainType} from './Animal';

class Dog extends Animal {
constructor() {
super({
name: 'Dog',
sound: 'Wof!',
family: 'Canidae',
foodChainType: FoodChainType.Carnivorous,
});
}n
}

This is a simple way of extending a parent class and using the parent's definition of the child to compose a new class with almost the same interface as the parent.

 

How it works...

Classes in TypeScript work the same as other classes in languages such as Java or C#. The compiler evaluates these common principles during development and compilation.

In this case, we made a simple class that had some public properties that were inherent by the children's classes. These variables were all readable and can be mutated.

 

There's more...

In TypeScript, we have a wide range of possible uses for classes, such as abstract classes, special modifiers, and using classes as interfaces. We've just covered the basics of the classes here to give us a good starting knowledge base. If you want to go deeper, the TypeScript documentation is very helpful and has a lot of examples that can help in the process of learning.

 

See also

 

Creating your first project with Vue CLI

When the Vue team realized that developers were having problems creating and managing their applications, they saw an opportunity to create a tool that could help developers around the world. The Vue CLI project was born.

The Vue CLI tool is a CLI tool that is used in terminal commands, such as Windows PowerShell, Linux Bash, or macOS Terminal. It was created as a starting point for the development of Vue, where developers can start a project and manage and build it smoothly. The focus of the Vue CLI team when developing was to give developers the opportunity to have more time to think about the code and spend less time on the tooling needed to put their code into production, adding new plugins or a simple hot-module-reload.

The Vue CLI tool is tweaked in such a way that there is no need to eject your tooling code outside the CLI before putting it into production.

When version 3 was released, the Vue UI project was added to the CLI as the main function, transforming the CLI commands into a more complete visual solution with lots of new additions and improvements.

 

Getting ready

The pre-requisite for this recipe is as follows:

  • Node.js 12+

The Node.js global objects that are required are as follows:

  • @vue/cli
  • @vue/cli-service-global
 

How to do it...

To create a Vue CLI project, follow these steps:

  1. We need to open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:
> vue create my-first-project
  1. The CLI will ask some questions that will help with the creation of the project. You can use the arrow keys to navigate, the Enter key to continue, and the Spacebar to select an option:
? Please pick a preset: (Use arrow keys)
default (babel, eslint)
Manually select features
  1. There are two methods for starting a new project. The default method is a basic babel and eslint project without any plugin or configuration, and the Manually mode, where you can select more modes, plugins, linters, and options. We will go for Manually.‌
  2. Now, we are asked about the features that we will want on the project. Those features are some Vue plugins such as Vuex or Router (Vue-Router), testers, linters, and more:
? Check the features needed for your project: (Use arrow keys)
Babel
TypeScript
Progressive Web App (PWA) Support
Router
Vuex
CSS Pre-processors
Linter / Formatter
Unit Testing
E2E Testing
  1. For this project, we will choose CSS Pre-processors and press Enter to continue:
? Check the features needed for your project: (Use arrow keys)
Babel
TypeScript
Progressive Web App (PWA) Support
Router
Vuex
CSS Pre-processors
Linter / Formatter
Unit Testing
E2E Testing
  1. It's possible to choose the main Cascading Style Sheets (CSS) preprocessors to be used with Vue—Sass, Less, and Stylus. It's up to you to choose which fits the most and is best for you:
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules
are supported by default):
(Use arrow keys)
Sass/SCSS (with dart-sass)
Sass/SCSS (with node-sass)
Less
Stylus
  1. It's time to format your code. You can choose between AirBnB, Standard, and Prettier with a basic config. Those rules that are imported inside the ESLint can be always customized without any problem and there is a perfect one for your needs. You know what is best for you:
? Pick a linter / formatter config: (Use arrow keys)
ESLint with error prevention only
ESLint + Airbnb config
ESLint + Standard config
ESLint + Prettier
  1. After the linting rules are set, we need to define when they are applied to your code. They can be either applied on save or fixed on commit:
? Pick additional lint features: (Use arrow keys)
Lint on save
Lint and fix on commit
  1. After all those plugins, linters, and processors are defined, we need to choose where the settings and configs are stored. The best place to store them is on a dedicated file, but it is also possible to store then on the package.json file:
? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
In dedicated config files
In package.json
  1. Now, you can choose if you want to make this selection a preset for future projects so that you don't need to reselect everything again:
? Save this as a preset for future projects? (y/N) n
  1. The CLI will automatically create the folder with the name you set in the first step, install everything, and configure the project.

You are now able to navigate and run the project. The basic commands on Vue CLI projects are as follows:

  • npm run serve—For running a development server locally
  • npm run build—For building and minifying the application for deployment
  • npm run lintTo execute the lint on the code

You can execute those commands via the Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows).

 

There's more...

The CLI has a tool inside it called Vue UI that helps in the process of managing your Vue projects. This tool will take care of the project dependencies, plugins, and configurations.

Each npm script in the Vue UI tool is named as Tasks, and on those tasks, you can get real-time statistics such as—for example—the size of the assets, modules, and dependencies; numbers of errors or warnings; and more deep networking data for fine-tuning your application.

To enter the Vue UI interface, you need to open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:

> vue ui
 

See also

 

Adding plugins to a Vue CLI project with Vue UI

The Vue UI tool is one of the most powerful additional tools for Vue development. It makes a developer's life easier, and at the same time can help manage the Vue projects.

 

Getting ready

The pre-requisite for this recipe is as follows:

  • Node.js 12+

The Node.js global objects that are required are as follows:

  • @vue/cli
  • @vue/cli-service-global
 

How to do it...

First, we need to create our Vue CLI project. To find how to create a Vue CLI project, please check the 'Creating your first project with Vue CLI' recipe. We can use the one we created in the last recipe or start a new one. Now, follow the instructions to add a plugin:

  1. Open the Vue UI interface. Open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:
> vue ui
  1. A new browser window will appear, with the Vue UI interface:

Here, you can list your projects, create a new project, or import an existing one.

  1. Now, we will import the one we created:

You need to find the folder that you created and click on Import this folder.

  1. After the folder is imported, the default Dashboard of the project will appear:

Here, it's possible to customize your Dashboard, adding new widgets, by clicking on the Customize button on the top:

  1. To add a new plugin, you must click on the Plugins menu in the left-hand sidebar:

The base plugins that you added on the Vue CLI tool will be already listed here.

  1. Now, we will add the base Vue ecosystem plugins—vuex and vue-router:

  1. If you check your code, you will see that the main.js file was changed, and the vuex (store) and vue-router (router) plugins are now imported and injected to the Vue instance:
 

How it works...

The Vue UI plugins work in conjunction with npm or yarn to automatically install the packages on your project, and then inject—when possible—the necessary conditions on the Vue instance.

If a plugin is a visual, directive, or a non-direct instantiated plugin, the Vue UI will install it and manage it, but you need to import it for use on your application.

 

Adding TypeScript to a Vue CLI project

Using TypeScript in a JavaScript project, even for static type checking, is good practice. It helps minimize the chance of errors and Object problems inside your project.

Adding TypeScript to a Vue project with the help of the Vue UI is very simple, and you will be able to use JavaScript code with TypeScript.

 

Getting ready

The pre-requisite for this recipe is as follows:

  • Node.js 12+

The Node.js global objects that are required are as follows

  • @vue/cli
  • @vue/cli-service-global
 

How to do it...

First, we need to create our Vue CLI project. To find how to create a Vue CLI project, please check the 'Creating your first project with Vue CLI' recipe. We can use the one we created in the last recipe or start a new one.

To add TypeScript to a Vue CLI project, follow these steps:

  1. Open the Vue UI interface. Open the Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:
> vue ui
  1. On your project, go to the Plugins manager, click on + Add plugin, and search for @vue/cli-plugin-typescript:

  1. Now, click on the Install @vue/cli-plugin-typescript button at the bottom of the page:
  1. You will be asked for some configuration settings after the plugin is downloaded, before the final installation:
    • Use class-style component syntax? Use the vue-class-component plugin with TypeScript.
    • Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Activate Babel to transpile TypeScript in addition to the TypeScript compiler.
    • Use ESLint? Use ESLint as a linter for the .ts and .tsx files.
    • Convert all .js files to .ts? Automatically convert all your .js files to .ts files in the installation process.
    • Allow .js files to be compiled? Activate the tsconfig.json flag to accept .js files in the compiler.
  2. After choosing your options, click on Finish the installation.
  3. Now, your project is a TypeScript Vue project, with all the files configured and ready to be coded:
 

How it works...

The Vue UI as a plugin manager will download the TypeScript package made for Vue, and install and configure it for you with the settings you choose.

Your project will be changed and modified according to your specifications, and will then be ready for development.

 

See also

 

Creating your first TypeScript Vue component with vue-class-component

As Vue components are object-based and have a strong relationship with the this keyword of the JavaScript object, it gets a little bit confusing to develop a TypeScript component.

The vue-class-component plugin uses the ECMAScript decorators proposal to pass the statically typed values directly to the Vue component and makes the process of the compiler understand what is happening more easily.

 

Getting ready

The pre-requisite for this recipe is as follows:

  • Node.js 12+

The Node.js global objects that are required are as follows:

  • @vue/cli
  • @vue/cli-service-global
 

How to do it...

First, we need to create our Vue CLI project. We can use the one we created in the last recipe or start a new one. To find how to create a Vue CLI project with TypeScript, please check the 'Adding TypeScript to a Vue CLI project' recipe.

Follow the instructions to create your first Vue component with Typescript and vue-class-component:

  1. Create a new file inside the src/components folder, called Counter.vue.
  2. Now, let's start making the script part of the Vue component. We will make a class that will have data with a number, two methods—one for increasing and another for decreasing—and, finally, a computed property to format the final data:
<script lang="ts">
import Vue from 'vue';
import Component from 'vue-class-component';

@Component
export default class Counter extends Vue {
valueNumber: number = 0;

get formattedNumber() {
return `Your total number is: ${this.valueNumber}`;
}

increase() {
this.valueNumber += 1;
}

decrease() {
this.valueNumber -= 1;
}
}
</script>
  1. It's time to create the template and rendering for this component. The process is the same as a JavaScript Vue file. We will add the buttons for increasing and decreasing the value and showing the formatted text:
<template>
<div>
<fieldset>
<legend>{{ formattedNumber }}</legend>
<button @click="increase">Increase</button>
<button @click="decrease">Decrease</button>
</fieldset>
</div>
</template>
  1. In the App.vue file, we need to import the component we just created:
<template>
<div id="app">
<Counter />
</div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import Counter from './components/Counter.vue';

@Component({
components: {
Counter,
},
})
export default class App extends Vue {

}
</script>
<style lang="stylus">
#app
font-family 'Avenir', Helvetica, Arial, sans-serif
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
text-align center
color #2c3e50
margin-top 60px
</style>
  1. Now, when you run the npm run serve command on Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows), you will see your component running and executing on screen:
 

How it works...

The vue-class-component plugin makes use of the new proposal of decorators to inject and pass some attributes to the classes on TypeScript.

This injection helps in the process of simplifying the development of a component with a syntax more aligned with TypeScript than with the Vue common object.

 

See also

 

Creating a custom mixin with vue-class-component

In Vue, a mixin is a way to reuse the same code in other Vue objects, like mixing all the property of the mixin inside the component.

When using a mixin, Vue first declares the mixin property and then the component values, so the components will be always the last and valid values. This merge occurs in a deep mode and has a specific way already declared inside the framework, but it can be changed by a special config.

With the use of mixins, developers can write tiny pieces of code and reuse them in lots of components.

This approach simplifies your work and allows you to complete tasks quicker.

 

Getting ready

The pre-requisite for this recipe is as follows:

  • Node.js 12+

The Node.js global objects that are required are as follows:

  • @vue/cli
  • @vue/cli-service-global
 

How to do it...

First, we need to create our Vue CLI project. We can use the one we created in the last recipe or start a new one. To find how to create a Vue CLI project with TypeScript, please check the 'Creating your first TypeScript Vue component with vue-class-component' recipe.

In this recipe, we will split it into two separate parts. First, we will create the counter component, and then we will use the code that is shared to create the mixin.

 

Creating the Counter component

Now, follow the instructions to create a custom mixin with vue-class-component:

  1. We need to make a new component called CounterByTen.vue in the src/components folder.
  2. Now, let's start making the script part of the Vue component. We will make a class that will have a variable with the type of a number and a default value of 0; two methods, one for increasing by 10 and another for decreasing by 10; and, finally, a computed property to format the final data:
<script lang="ts">
import Vue from 'vue';
import Component from 'vue-class-component';

@Component
export default class CounterByTen extends Vue {
valueNumber: number = 0;

get formattedNumber() {
return `Your total number is: ${this.valueNumber}`;
}

increase() {
this.valueNumber += 10;
}

decrease() {
this.valueNumber -= 10;
}
}
</script>
  1. It's time to create the template and rendering for this component. The process is the same as for a JavaScript Vue file. We will add the buttons for increasing and decreasing the value and for showing the formatted text:
<template>
<div>
<fieldset>
<legend>{{ this.formattedNumber }}</legend>
<button @click="increase">Increase By Ten</button>
<button @click="decrease">Decrease By Ten</button>
</fieldset>
</div>
</template>
  1. In the App.vue file, we need to import the component we just created:
<template>
<div id="app">
<Counter />
<hr />
<CounterByTen />
</div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import Counter from './components/Counter.vue';
import CounterByTen from './components/CounterByTen.vue';

@Component({
components: {
Counter,
CounterByTen,
},
})
export default class App extends Vue {

}
</script>
<style lang="stylus">
#app
font-family 'Avenir', Helvetica, Arial, sans-serif
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
text-align center
color #2c3e50
margin-top 60px
</style>
 

Extracting similar code for the mixin

With both of the components having similar code, we can extract this similar code and create a mixin. This mixin can be imported in both of the components and their behavior will be the same:

  1. Create a file called defaultNumber.ts in the src/mixins folder.
  2. To code our mixin, we will import the Component and Vue decorators from the vue-class-component plugin, to be the base of the mixin. We will need to take a similar code and place it inside the mixin:
import Vue from 'vue';
import Component from 'vue-class-component';

@Component
export default class DefaultNumber extends Vue {
valueNumber: number = 0;

get formattedNumber() {
return `Your total number is: ${this.valueNumber}`;
}
}
  1. With the mixin ready, open the Counter.vue component on the src/components folder and import it. To do this, we need to import a special export from the vue-class-component called mixins and extend it with the mixin we want to extend. This will remove the Vue and Component decorators because they are already declared on the mixin:
<template>
<div>
<fieldset>
<legend>{{ this.formattedNumber }}</legend>
<button @click="increase">Increase By Ten</button>
<button @click="decrease">Decrease By Ten</button>
</fieldset>
</div>
</template>

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

@Component
export default class CounterByTen extends mixins(DefaultNumber) {
increase() {
this.valueNumber += 10;
}

decrease() {
this.valueNumber -= 10;
}
}
</script>
  1. Now, when you run the npm run serve command on Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows), you will see your component running and executing on screen:
 

How it works...

The process of using mixins with TypeScript is the same as with the Vue objects. The code that is shared can be split into smaller files and called in the components for easier coding.

When using TypeScript and vue-class-component, the Vue and Component decorators need to be declared on the mixins because the class that will be using the mixin will already have this extension, as it extends this mixin.

We took the same piece of code that works the same on both the components and placed it in a new file that is then called in both of the components.

 

See also

 

Creating a custom function decorator with vue-class-component

Decorators were introduced in ECMAScript 2015. A decorator is a kind of high-order function that wraps a function with another function.

This brings a lot of new improvements to the code—along with greater productivity—because it takes the principle of functional programming and simplifies it.

 

Getting ready

The pre-requisite for this recipe is as follows:

  • Node.js 12+

The Node.js global objects that are required are as follows:

  • @vue/cli
  • @vue/cli-service-global
 

How to do it...

First, we need to create our Vue CLI project. To find how to create a Vue CLI project, please check the 'Creating your first project with Vue CLI' recipe. We can use the one we created in the last recipe or start a new one.

Follow these steps to create your custom function decorator with vue-class-component:

  1. Create a file called componentMount.js inside the src/decorators folder.
  2. We need to import the createDecorator function from the vue-class-component to be able to use it on a vue-class-component based component, and to start coding our decorator:
import { createDecorator } from 'vue-class-component';
import componentMountLogger from './componentLogger';

export default createDecorator((options) => {
options.mixins = [...options.mixins, componentMountLogger];
});
A createDecorator function is like an extension of the Vue vm (View-Model), so it won't have the property of an ECMAScript decorator but will function as a Vue decorator.
  1. We need to use the componentLogger.js file in our decorator. This function will take all the data values that are set in the "decorated" component and add a watcher to it. This watcher will log the new and old values whenever it changes. This function will only be executed with a debug data set to true:
export default {
mounted() {
if (this.debug) {
const componentName = this.name || '';
console.log(`The ${componentName} was mounted
successfully.`);

const dataKeys = Object.keys(this.$data);

if (dataKeys.length) {
console.log('The base data are:');
console.table(dataKeys);

dataKeys.forEach((key) => {
this.$watch(key, (newValue, oldValue) => {
console.log(`The new value for ${key} is:
${newValue}`);
console.log(`The old value for ${key} is:
${oldValue}`);
}, {
deep: true,
});
});
}
}
},
};
  1. Now, we need to import the decorator to our Counter.vue component file located in the src/components folder and add the debugger data to it:
<template>
<div>
<fieldset>
<legend>{{ this.formattedNumber }}</legend>
<button @click="increase">Increase</button>
<button@click="decrease">Decrease</button>
</fieldset>
</div>
</template>

<script lang="ts">
import Vue from 'vue';
import Component from 'vue-class-component';
import componentMount from '../decorators/componentMount';

@Component
@componentMount
export default class Counter extends Vue {
valueNumber: number = 0;

debug: boolean = true;

get formattedNumber() {
return `Your total number is: ${this.valueNumber}`;
}

increase() {
this.valueNumber += 1;
}

decrease() {
this.valueNumber -= 1;
}
}
</script>
 

How it works...

The createDecorator function is a factory function that extends the Vue vm (View Model), which produces an extension of the Vue component, such as a Vue mixin. A Vue mixin is a property of the Vue component that can be used to share and reuse code between components.

When we call the mixin, it takes the current component as an option of the first argument (the key if it was attached to a property), and the index of it.

We added a dynamic debugger that is only attached when debug data exists and is set to true. This debugger will log the current data and set watchers for the changes in the data, showing the logs on the console each time the data is changed.

 

There's more...

When using linters, some rules can be a problem with decorators. So, it's wise to disable them only on the files that are having problems with the rules that are required for the code to work.

In an AirBnB style, for example, the no-param-reassign rule is required because the decorator uses the option as a reference to pass the value.

 

See also

 

Adding custom hooks to vue-class-component

On Vue, it's possible to add hooks to its life cycle through the Plugins application programming interface (API). The most basic example is the vue-router with the navigation guards, such as the beforeRouterEnter and beforeRouterLeave functions hooks.

The hooks, as the name implies, are little functions that are called each time something will happen.

You can take advantage of the hooks and make them more powerful, adding new functionalities to your components, such as checking for special security access, adding meta search engine optimization (SEO), or even pre-fetching data.

 

Getting ready

The pre-requisite for this recipe is as follows:

  • Node.js 12+

The Node.js global objects that are required are as follows:

  • @vue/cli
  • @vue/cli-service-global
 

How to do it...

First, we need to create our Vue CLI project. We can use the one we created in the last recipe or start a new one. To find how to create a Vue CLI project with TypeScript, please check the 'Adding TypeScript to a Vue CLI project' recipe.

Now, follow these steps to add custom hooks to your Vue project using TypeScript and vue-class-component:

  1. We need to add vue-router to the project. This can be done with the Vue CLI project creation or in the Vue UI interface after the project has been created.
If prompted about the mode, the vue-router should run. Take note that selecting the History option will require special server configuration when it's time to deploy.
  1. Open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the npm run serve command, and you will see that the vue-router is working and that there are two working routers: home and about.
  1. Let's start creating and naming our hooks to register on the main application. To do this, we need to create a vue-router.js file inside the src/classComponentsHooks folder:
import Component from 'vue-class-component';

Component.registerHooks([
'beforeRouteEnter',
'beforeRouteLeave',
]);
  1. We need to import this file to the main.ts file as it needs to be called before the application final build:
import './classComponentsHooks/vue-router';

import Vue from 'vue';
import App from './App.vue';
import router from './router';

Vue.config.productionTip = false;

new Vue({
router,
render: h => h(App),
}).$mount('#app');
  1. We now have the hooks registered on the vue-class-component and they can be used inside the TypeScript components.
  1. We need to create a new router location called Secure.vue in the src/views folder. The secure page will have a password to enter, vuejs. When the user enters this password, the router guard will grant permission, and the user can see the page. If the password is wrong, the user will be taken back to the home page. When they leave the page, an alert will show a message to the user:
<template>
<div class="secure">
<h1>This is an secure page</h1>
</div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { Route, RawLocation } from 'vue-router';

type RouteNext = (to?: RawLocation | false | ((vm: Vue) => any) |
void) => void;

@Component
export default class Home extends Vue {
beforeRouteEnter(to: Route, from: Route, next: RouteNext) {
const securePassword = 'vuejs';

const userPassword = prompt('What is the password?');

if (userPassword === securePassword) {
next();
} else if (!userPassword) {
next('/');
}
}

beforeRouteLeave(to: Route, from: Route, next: RouteNext) {
alert('Bye!');
next();
}
}
</script>
  1. Now with our page done, we need to add it to the router.ts file to be able to call it in the Vue application:
import Vue from 'vue';
import Router from 'vue-router';
import Home from './views/Home.vue';

Vue.use(Router);

export default new Router({
routes: [
{
path: '/',
name: 'home',
component: Home,
},
{
path: '/about',
name: 'about',
component: () => import('./views/About.vue'),
},
{
path: '/secure',
name: 'secure',
component: () => import('./views/Secure.vue'),
},
],
});
  1. With the route added and the view created, the final step is to add the link to the main App.vue file, and we will have a component with an integrated hook on it:
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/secure">Secure</router-link>
</div>
<router-view/>
</div>
</template>
<style lang="stylus">
#app
font-family 'Avenir', Helvetica, Arial, sans-serif
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
text-align center
color #2c3e50

#nav
padding 30px
a
font-weight bold
color #2c3e50
&.router-link-exact-active
color #42b983
</style>
 

How it works...

The class component needs to understand what are the navigation guards that are being added to the Vue prototype before executing the Vue application. Because of this, we needed to import the custom hooks on the first line of the main.ts file.

In the component, with the hooks registered, it's possible to add them as methods because the vue-class-component has made all those custom imports into base methods for the component decorator.

We used two of the vue-router navigation guards' hooks. Those hooks are called each time a route will enter or leave. The first two parameters we didn't use, the to and from parameters, are the ones that carry information about the future route and the past route.

The next function is always required because it executes a route change. If no argument is passed in the function, the route will continue with the one that was called, but if you want to change the route on the fly, it is possible to pass an argument to change where the user will go.

 

See also

 

Adding vue-property-decorator to vue-class-component

Some of the most important parts of Vue are missing in the vue-class-component in the form of TypeScript decorators. So, the community made a library called vue-property-decorator that is fully endorsed by the Vue core team.

This library brings some of the missing parts as ECMAScript proposal decorators, such as props, watch, model, inject, and so on.

 

Getting ready

The pre-requisite for this recipe is as follows:

  • Node.js 12+

The Node.js global objects that are required are as follows:

  • @vue/cli
  • @vue/cli-service-global
 

How to do it...

First, we need to create our Vue CLI project. We can use the one we created in the last recipe or start a new one. To find how to create a Vue CLI project with TypeScript, please check the 'Creating a custom mixin with vue-class-component' recipe.

Follow these steps to add vue-property-decorator to a Vue class-based component:

  1. We need to add the vue-property-decorator to our project. Open Terminal (macOS or Linux) or Command Prompt/PowerShell (Windows) and execute the following command:
> npm install -S vue-property-decorator
  1. In the components mixin, we will add a decorator for receiving a prop, which will be a value for our number that is calculated:
import {
Vue,
Component,
Prop,
} from 'vue-property-decorator';

@Component
export default class DefaultNumber extends Vue {
valueNumber: number = 0;

@Prop(Number) readonly value: number | undefined;

get formattedNumber() {
return `Your total number is: ${this.valueNumber}`;
}
}
  1. With that number, we need to make the watchers emit the event to the parent component when the value changes, and update the value inside when the value is changed within the parent component. To do this, we need to create a new file called numberWatcher.ts inside the src/mixins folder:
import {
Watch,
Mixins,
} from 'vue-property-decorator';
import DefaultNumber from './defaultNumber';

export default class NumberWatchers extends Mixins(DefaultNumber) {
@Watch('valueNumber')
onValueNumberChanged(val: number) {
this.$emit('input', val);
}

@Watch('value', { immediate: true })
onValueChanged(val: number) {
this.valueNumber = val;
}
}

In Vue, the v-model directive works like a sugar syntax, as a combination of the Vue $emit function and the Vue props function. When the value is changed, the component needs to $emit with the 'input' name, and the component needs to have in the props function a value key, which will be the value that will be passed down from the parent component to the child component.
  1. With our mixin updated, our components need to be updated too. First, we will update the Counter.vue component, changing the imported mixin from the defaultNumber.ts file to numberWatcher.ts:
<template>
<div>
<fieldset>
<legend>{{ this.formattedNumber }}</legend>
<button @click="increase">Increase</button>
<button @click="decrease">Decrease</button>
</fieldset>
</div>
</template>

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

@Component
export default class Counter extends mixins(NumberWatcher) {
increase() {
this.valueNumber += 1;
}

decrease() {
this.valueNumber -= 1;
}
}
</script>
  1. Now, we will update the CounterByTen.vue component, and add the newly created mixin:
<template>
<div>
<fieldset>
<legend>{{ this.formattedNumber }}</legend>
<button @click="increase">Increase By Ten</button>
<button @click="decrease">Decrease By Ten</button>
</fieldset>
</div>
</template>

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

@Component
export default class CounterByTen extends mixins(NumberWatcher) {
increase() {
this.valueNumber += 10;
}

decrease() {
this.valueNumber -= 10;
}
}
</script>
  1. With everything settled, we just need to update the App.vue component. This time, we will store a variable in the component that will be passed down to both of the child components, and when the components emit the update events, this variable will change automatically, updating the other components too:
<template>
<div id="app">
<Counter
v-model="amount"
/>
<hr />
<CounterByTen
v-model="amount"
/>
</div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import Counter from './components/Counter.vue';
import CounterByTen from './components/CounterByTen.vue';

@Component({
components: {
Counter,
CounterByTen,
},
})
export default class App extends Vue {
amount: number = 0;
}
</script>
<style lang="stylus">
#app
font-family 'Avenir', Helvetica, Arial, sans-serif
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
text-align center
color #2c3e50
margin-top 60px
</style>
 

How it works...

By injecting the decorators at the vue-class-components, the vue-property-decorator helps the TypeScript compiler check for the types and static analysis of your Vue code.

We used two of the decorators available, the @Watch and @Prop decorators.

As we took apart the common parts of our code in the form of mixins, the process implementation became easier.

The parent component passed down a property to the child component, passing the initial value and the subsequently updated value.

This value is checked and updated inside the child component, which is used to update a local variable used by the calculation functions. When the calculation is done and the value is changed, the watcher emits an event that is passed to the parent component, which updates the main variable, and the loop goes on.

 

There's more...

There is another library that works the same as the vue-property-decorator, but for the vuex plugin, called vuex-class.

This library uses the same process as vue-property-decorator. It creates an inject decorator in the component. Those decorators help the TypeScript compiler to check for types in the development process.

You can find more information about this library at https://github.com/ktsn/vuex-class/

 

See also

About the Author
  • Heitor Ramon Ribeiro

    Heitor Ramon Ribeiro has been developing for the web for over 15 years. Heitor has built enterprise applications for businesses using Vue.js and the principles of clean architecture, shifting his course from legacy applications to the new world of single-page applications (SPAs) and progressive web applications (PWAs). He thinks that almost anything is possible today with a browser and that JavaScript is the future of programming. When he’s not programming or leading a frontend team, he’s with his family having fun, streaming their gaming sessions, or playing some first-person shooter games.

    Browse publications by this author
Latest Reviews (4 reviews total)
The CookBook format makes it interesting to learn the framework through examples
Excelent book from experienced author. The book is well divided into chapters. Lots of external resources to study. I would like to read more such good books.
Great content, Great content
Vue.js 3 Cookbook
Unlock this book and the full library FREE for 7 days
Start now