How to write a vue. js app completely in TypeScript

By Preetish HS

Translator:!

Both Typescript and Vue are now front-end essentials. This article covers the basic usages of Vue 2.x in Typescript versions, and will help you prepare for Vue 3.0

The translator wrote one by himself according to the knowledge points mentioned in the articledemo, has been inGithub address, I suggest you can practice, if you encounter any problems, you can leave comments or mentionissue

Vue is an amazing, lightweight, progressive front-end framework. Because Vue is flexible, users do not need to use Typescript. But unlike Angular, older versions of Vue don’t have good support for Typescript. Because of this, most Vue applications are written directly in JavaScript.

Now with official support for Typescript, you can create Typescript projects from scratch using the Vue CLI. But we still need some third-party packages with custom decorators and features to create a real, full Typescript application, and the official documentation doesn’t contain all the information you need to get started.

To help you understand it fully, we’ll show you how to build a new Vue + TypeScript application using the Vue CLI.

start

Start with the following code

vue create typescript-app
Copy the code

Select the manual selection function and configure it, as shown below

Once the project is set up, we run the project

cd typescript-app
npm run serve
Copy the code

The localhost:8080 page will be automatically opened (or the link will be printed after you start the project), indicating that our project has started successfully

As we go through this tutorial, we will review the following features and show how to implement them using Typescript

2.Data, props, computed, Methods, Watchers, and Emit 3. Life cycle 4.Mixins 5

Open helloWorld.vue in the Components directory and you will see the following structure

Note: For each instance, I’ll display both TypeScript and Javascript equivalent code so you can easily compare the two. Let’s get started

1. Class-based components

//Typescript code
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
@Component
export default class HelloWorld extends Vue {
}
</script>
Copy the code

The Javascript equivalent is as follows:

<script>
export default {
name: 'HelloWorld'
}
</script>
Copy the code

To use Typescript, we first need to set the lang property of

Is a third party package that takes the official Vue-class component package and adds more decorators to it.

Vue-property-decorator is a third-party package that takes the vue class component package and adds more decorators to it. If the class name is specified, the default name is the class name, but we can also explicitly use the name attribute to name the component.

@component({
  name: 'HelloWorld'
})
Copy the code

Introducing a component

The code to register other components in a Component is written in the @Component decorator, as shown below.

<template>
  <div class="main">
    <project />
  </div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import Project from '@/components/Project.vue'
@Component({
  components: {
    project
  }
})
export default class HelloWorld extends Vue {}</script>
Copy the code

The Javascript equivalent is as follows:

<template>
  <div class="main">
    <project />
  </div>
</template>
<script>
import Project from '@/components/Project.vue'
export default {
  name: 'HelloWorld'.components: {
    project
  }
})
</script>
Copy the code

2. Data, props, computed, methods, Watchers, and emit

Use the data

To use the data attributes, we can simply declare them as class variables.

@Component
export default class HelloWorld extends Vue {
  private msg: string = "welcome to my app"
  private list: Array<object> = [
    {
      name: 'Preetish'.age: '26'
    },
    {
      name: 'John'.age: '30'}}]Copy the code

The Javascript equivalent is as follows:

export default {
  data() {
    return {
      msg: "welcome to my app".list: [{name: 'Preetish'.age: '26'
        },
        {
          name: 'John'.age: '30'}}}]Copy the code

The use of props

We can use props in a Vue component using the @prop decorator. In Vue, we can give props for additional configurations such as required, default, and type. First we can introduce a Prop decorator from vue-property-decorator as follows. We can also use readonly to avoid manipulating change props.

import { Component, Prop, Vue } from 'vue-property-decorator'
@Component
export default class HelloWorld extends Vue { @Prop() readonly msg! : string @Prop({default: 'John doe'}) readonly name: string
  @Prop({required: true}) readonly age: number
  @Prop(String) readonly address: string
  @Prop({required: false.type: String.default: 'Developer'}) readonly job: string
}
</script>
Copy the code

The Javascript equivalent is as follows:

  props: {
    msg,
    name: {
      default: 'John doe'
    },
    age: {
      required: true,},address: {
      type: String
    },
    job: {
      required: false.type: string,
      default: 'Developer'}}}Copy the code

Computed properties

Computed properties are used to write simple template logic, such as manipulating, adding, or joining data. In TypeScript, a normal computed property is also prefixed with the get keyword.

export default class HelloWorld extends Vue {
  get fullName() :string {
    return this.first+ ' '+ this.last
  }
}
Copy the code

The Javascript equivalent is as follows:

export default {
  fullName() {
    return this.first + ' ' + this.last
  }
}
Copy the code

In Typescript, we can write complex computed properties that include getters and setters, as shown below

export default class HelloWorld extends Vue {
  get fullName() :string {
    return this.first+ ' '+ this.last
  }
  set fullName(newValue: string) {
    let names = newValue.split(' ')
    this.first = names[0]
    this.last = names[names.length - 1]}}Copy the code

The Javascript equivalent is as follows:

fullName: {
  get: function () {
    return this.first + ' ' + this.last
  },
  set: function (newValue) {
    let names = newValue.split(' ')
    this.first = names[0]
    this.last = names[names.length - 1]}}Copy the code

Methods

Like normal class methods, TypeScript methods have an optional access modifier.

export default class HelloWorld extends Vue {
  public clickMe(): void {
    console.log('clicked')
    console.log(this.addNum(4.2))
  }
  public addNum(num1: number, num2: number): number {
    return num1 + num2
  }
}
Copy the code

The Javascript equivalent is as follows:

export default {
  methods: {
    clickMe() {
      console.log('clicked')
      console.log(this.addNum(4.2))}addNum(num1, num2) {
      return num1 + num2
    }
  }
}
Copy the code

Watchers

The syntax for writing a Watcher is different from the way we normally write JavaScript. The most common syntax for writing a Watcher in JavaScript is as follows:

watch: {
  name: function(newval) {
    //do something
  }
}
Copy the code

We don’t use handler syntax very often

watch: {
  name: {
    handler: 'nameChanged'}}methods: {
  nameChanged (newVal) {
    // do something}}Copy the code

However, Typescript is similar to the second approach. In TypeScript, we use the @watch decorator and pass the name of the variable we want to monitor.

@Watch('name')
nameChanged(newVal: string) {
  this.name = newVal
}
Copy the code

We can also use immediate and deep

@Watch('project', { 
  immediate: true.deep: true 
})
projectChanged(newVal: Person, oldVal: Person) {
  // do something
}
Copy the code

The Javascript equivalent is as follows:

watch: {
  person: {
      handler: 'projectChanged'.immediate: true.deep: true}}methods: {
  projectChanged(newVal, oldVal) {
    // do something}}Copy the code

Emit

To emit a method from a child component to a parent component, in Typescript we would use the @emit decorator.

@Emit()
addToCount(n: number) {
  this.count += n
}
@Emit('resetData')
resetCount() {
  this.count = 0
}
Copy the code

In the first example, the function name addToCount is converted to a dash separated (kebab-case), which is very similar to how Vue Emit works.

In the second example, we pass the explicit name of the method, resetData, and use that name. Because addData is humped, it is again converted to a kebab-case.

<some-component add-to-count="someMethod" />
<some-component reset-data="someMethod" />
Copy the code
//Javascript Equivalent
 methods: {
    addToCount(n) {
      this.count += n
      this.$emit('add-to-count', n)
    },
    resetCount() {
      this.count = 0
      this.$emit('resetData')}}Copy the code

3. Lifecycle hooks

A Vue component has eight lifecycles, including created, Mounted, and so on, and each hook uses the same Typescript syntax. These are declared as plain class methods. Because lifecycle hooks are called automatically, they neither accept arguments nor return any data. Therefore, we do not need to access modifiers, input parameters, or return types.

export default class HelloWorld extends Vue {
  mounted() {
    //do something
  }
  beforeUpdate() {
    // do something}}Copy the code

The Javascript equivalent is as follows:

export default {
  mounted() {
    //do something
  }
  beforeUpdate() {
    // do something}}Copy the code

4. Mixins

To create mixins in Typescript, we must first create mixin files that contain the data we share with other components.

Create a file called projectmixin.ts. Add the following mixin to the mixin directory, which shares projName and the methods to update projName.

import { Component, Vue } from 'vue-property-decorator'
@Component
class ProjectMixin extends Vue {
  public projName: string = 'My project'
  public setProjectName(newVal: string): void {
    this.projName = newVal
  }
}
export default ProjectMixin
Copy the code

The Javascript equivalent is as follows:

export default {
 data() {
   return {
     projName: 'My project'}},methods: {
   setProjectName(newVal) {
     this.projName = newVal
   }
 }
}
Copy the code

To use the above Mixins in our Vue component, we need to import Mixins and mixin files from the Vue-property-decorator, as shown below

//Projects.vue
<template>
  <div class="project-detail">
    {{ projectDetail }}
  </div>
</template>
<script lang="ts">
import { Component, Vue, Mixins } from 'vue-property-decorator'
import ProjectMixin from '@/mixins/ProjectMixin'
@Component
export default class Project extends Mixins(ProjectMixin) {
  get projectDetail() :string {
    return this.projName + ' ' + 'Preetish HS'}}</script>
Copy the code

The Javascript equivalent is as follows:

<template>
  <div class="project-detail">
    {{ projectDetail }}
  </div>
</template>
<script>
import ProjectMixin from '@/mixins/ProjectMixin'
export default {
  mixins: [ ProjectMixin ],
  computed: {
    projectDetail() {
      return this.projName + ' ' + 'Preetish HS'}}}</script>
Copy the code

5. Vuex

Vuex is the official state management library used in most vue.js applications. It is a good practice to divide stores into namespace modules. We’ll show you how to write it in TypeScript.

First, we need to install two popular third-party libraries:

npm install vuex-module-decorators -D
npm install vuex-class -D
Copy the code

In the Store folder, let’s create a Module folder to hold our namespace storage modules.

Create a file named user. Ts has the status of user.

// store/modules/user.ts
import { VuexModule, Module, Mutation, Action } from 'vuex-module-decorators'
@Module({ namespaced: true.name: 'test' })
class User extends VuexModule {
  public name: string = ' '
  @Mutation
  public setName(newName: string): void {
    this.name = newName
  }
  @Action
  public updateName(newName: string): void {
    this.context.commit('setName', newName)
  }
}
export default User
Copy the code

The vuex-mode-Decorators library provides decorators for Modules, mutations, and actions. State variables are declared directly, just like class variables. This is a simple module that stores the user name and updates the actions of the user name with an mutation and an action.

We don’t need state as the first parameter in Mutations and Actions, the library already takes that into account. It has been injected into those methods.

The Javascript equivalent is as follows:

export default {
  namespaced: true.state: {
    name: ' '
  },
  mutations: {
    setName(state, newName) {
      state.name = newName
    }
  },
  actions: {
    updateName(context, newName) {
      context.commit('setName', newName)
    }
  }
}
Copy the code

In the store folder, we need to create an index.ts to initialize Vuex and register the module

import Vue from 'vue'
import Vuex from 'vuex'
import User from '@/store/modules/user'
Vue.use(Vuex)
const store = new Vuex.Store({
  modules: {
    User
  }
})
export default store
Copy the code

Use Vuex in components

To use Vuex, we can take advantage of a library called vuex-Class. This library provides decorators to bind State, Getter, Mutation, and Action in the Vue component.

Since we are using the Vuex module with a namespace, we first import the namespace from the Vuex class and then pass the module name to access the module.

<template>
  <div class="details">
    <div class="username">User: {{ nameUpperCase }}</div>
    <input :value="name" @keydown="updateName($event.target.value)" />
  </div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { namespace } from 'vuex-class'
const user = namespace('user')
@Component
export default class User extends Vue { @user.State public name! : string @user.Getter public nameUpperCase! : string @user.Action public updateName! :(newName: string) = > void
}
</script>
Copy the code

The Javascript equivalent is as follows:

<template>
  <div class="details">
    <div class="username">User: {{ nameUpperCase }}</div>
    <input :value="name" @keydown="updateName($event.target.value)" />
  </div>
</template>
<script>
import { mapState, mapGetters, mapActions} from 'vuex'
export default  {
  computed: {
    ...mapState('user'['name']),
    ...mapGetters('user'['nameUpperCase'])}methods: {
    ...mapActions('user'['updateName'])}}</script>
Copy the code

conclusion

Now that you have all the basic information you need to fully create vue.js applications in TypeScript, you can use official and third-party libraries to take full advantage of the typing and custom decorator features. Vue 3.0 will provide better support for TypeScript, and the entire Vue.js code will be rewritten in TypeScript to improve maintainability.

Working with TypeScript can seem overwhelming at first, but once you get used to it, your code will have fewer bugs, and code collaboration between other developers on the same code base will be smoother.