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.