Book Image

Vue.js 3 Cookbook

By : Heitor Ramon Ribeiro
Book Image

Vue.js 3 Cookbook

By: Heitor Ramon Ribeiro

Overview of 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.
Table of Contents (13 chapters)
5
Fetching Data from the Web via HTTP Requests
6
Managing Routes with vue-router
7
Managing the Application State with Vuex
11
Directives, Plugins, SSR, and More
Vue

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>