Hey, hey, hey, hey, hey, hey, hey, hey, hey. I’m back.
This is the end of the TypeScript basics tutorial series, which will show you how to apply TypeScript to your projects to help those who don’t already know how.
Statement (or this statement) : โจ this series of articles as the basis of the tutorial, does not involve deep things, more suitable for beginners to see, if the students have already met, read this paragraph of text can run away ๐.
Used in Vue projects
While the previous two articles covered the basics and deeper stuff of TypeScript, this chapter shows you how to use it in Vue projects.
Project creation
Create a project directly using vue-CLI
Here are the steps:
1. Run Vuecli
2. Select an appropriate directory to create the project
3. Enter the project name, select package Manager, and enter git repository initialization content
4. Set the preset, if you have a suitable preset, you can set the preset, select manual
5. Select features, where TypeScript and Babel are mandatory and other features depend on the project:
6. Set the configuration, turn on class style component syntax (item 1), select ESLint to configure to ESLint+Standard (item 5), and turn on save time check and fix code
7. Create projects
8. Install plug-ins
Editor files support Settings
Take Webstrom as an example:
Go to Editor>File and COde Templates
Create a new code template, enter a name with the extension vue, select Reformat according to style, and select enable the template
Content area input:
<template lang="pug">
#[[$END$]]#
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
@Component
export default class ${COMPONENT_NAME} extends Vue {
}
</script>
<style lang="stylus" rel="stylesheet/stylus" module>
</style>
Copy the code
After clicking Apply, select the template you created when creating a new file:
Because we chose class style syntax, we need to fill in the class name:
Modify ESLint, editor configuration
Modify the ESLint configuration file to support checking TypeScript files
Add the following code to the.eslintrc.js parserOptions option:
parser: '@typescript-eslint/parser'
Copy the code
Modify the editor configuration to support automatic code repair when saving
One of webstrom’s strengths is its support for various technologies, such as esLint checking code. Normally, we would need to check code from the command line, which is cumbersome, but Webstrom can configure ESLint, check for code that is not configured for ESLint in the editor, and support save time fixes. The configuration is as follows:
Modify declaration file
For our custom plug-ins, global methods, global variables, etc., TypeScript doesn’t know about them. To let TypeScript know about them, we can declare files that tell TypeScript, If we use $style in model style, we modify the shims-tsx.d.ts file and add the following code at the end of the line:
declare module 'vue/types/vue' { interface Vue { $style: { [key: string]: string; }; } interface VueConstructor { $style: { [key: string]: string; }; }}Copy the code
This is similar for other things
Use in components
Basic usage
Because you use class style to write JS in a component, you write it slightly differently, but essentially the same.
A component reference
Component references are made by passing the parameter components to the decorator @component
@Component({
components: {
MapLegend: () => import('@/components/legend/index.vue')
}
})
Copy the code
The filter
Filters, like components, define local filters within the filters object by passing the filters parameter:
@Component({
filters: {
dateFormat (date:Date) {
return dateFormat(date)
}
}
})
Copy the code
instruction
Local directives are like filters, passing the parameter directives via the @Component decorator:
@Component({
directives:{
focus: {
inserted: function (el) {
el.focus()
}
}
}
})
Copy the code
props
Props is no longer defined as an object property, but as the @prop decorator, whose configuration content is passed in as a parameter:
@Component export default class Test extends Vue { @Prop({ type:String, default:'no name', required:false }) name! :string mounted(){ console.log(name) } }Copy the code
Synchronous version of props
Using @propSync, you can create a synchronous version of the props property (if the variable changes, the corresponding props property changes with it) :
@Component export default class Test extends Vue { @PropSync('name',{ type:String, default:'no name', required:false }) name! :string mounted(){ this.name='nichols' } }Copy the code
Listener (Watch)
Similarly, listeners are defined by the @watch decorator, which receives two parameters, the first to monitor which variable, and the second to other configurations:
@Component
export default class Test extends Vue {
isShow=false
@Watch('isShow',{
deep:true,
immediate:true
})
onIsShowChange(val:boolean,newVal:boolean){
}
}
Copy the code
A listener can also be treated as a method call, executing its internal logic:
mounted(){
this.onIsShowChange(true,false)
}
Copy the code
emit
Raising an event in a component to be listened to by the parent is a very common operation. The @emit decorator defines a function that can be called as a normal function:
@Component
export default class Test extends Vue {
name = ''
@Emit('change')
onChange (name: string) {
this.name = name
}
mounted () {
this.onChange('nichols')
}
}
Copy the code
If there is a return value, the return value is placed first as the triggered parameter, and the passed parameter is placed after the return value
ref
Define ref using the @ref decorator:
@Component export default class Test extends Vue { name = '' @Ref('form') form! :HTMLElement mounted(){ console.log(this.form.offsetHeight) } }Copy the code
data
For data within a component, we can define the component’s data directly using class attributes:
@Component
export default class Test extends Vue {
isShow = false
form: {
username: string;
password: string;
} = {
username: '',
password: ''
}
mounted () {
this.isShow = true
}
}
Copy the code
Functions (Methods)
The data function is similar to the data definition, adding a method to the class:
@Component export default class Test extends Vue { log(){ // .... }}Copy the code
Calculate attribute
Compute properties, on the other hand, are written as accessors for classes (getters, setters, corresponding to Vue getters and setters) :
@Component export default class Test extends Vue {lastName = 'Nicholas' firstName =' Joe 'get name (): String {return '${this.firstName}ยท${this.lastName}'} set name (name: String) {const names = name.split('ยท') this.firstName = names[0] this.lastName = names[0]}}Copy the code
The life cycle
You can define the corresponding hook name directly, or use vue-class-Component /hooks. D.ts:
@Component
export default class Test extends Vue {
mounted () {
}
created () {
}
updated () {
}
beforeDestroy () {
}
destroyed () {
}
}
Copy the code
More details
Refer to the VUe-property-decorator documentation for more details
Type declaration
Under the types directory of SRC, create index.d.ts (or more elaborate filename) and define the type, using the Event extension as an example:
interface Event{
DataTransfer:{
setData():void
}
}
Copy the code
To avoid global variable clutter, we can use export to export declarations that we want to access externally:
export interface User{
id:string;
name:string;
realName:string;
}
Copy the code
If you need to use it, import it in the place where you need to use it:
import { User } from '@/types/user'
@Component
export default class Test extends Vue {
user:User={
id: '',
name: '',
realName: ''
}
}
Copy the code
Migration of old projects
Installing a plug-in
1. Launch vue UI (a shuttle is dry!) Click Add Plug-in in the Plug-in TAB.
2. Search for TypeScript, select @vue/ CLI-pluging-typescript, and click Install
Modify the components
1. Script tag add attribute lang=”ts”
2. Component import Add. Vue suffix
3. Change the default export to class style:
export default {
name:'Component1'
}
Copy the code
Is amended as:
@Component
export default class Component1 extends Vue{
}
Copy the code
4. Change the corresponding data to the class style according to the basic usage
5. Add or modify type comments as prompted
Modifying js files
1. Change the extension of the js file to. Ts
2. Add type constraints
The use of vuex
Vuex and VUE components are used in a similar way, defined in the form of class style + decorators, using the dependency vuex-module-decorators,
The installation
yarn add vuex-module-decorators
npm i vuex-module-decorators
Copy the code
Create the Store
A Store is created in the same way as a regular Store:
import Vue from 'vue'
import Vuex from 'vuex'
import User from '@/store/modules/user'
import getters from '@/store/getters'
Vue.use(Vuex)
export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
getters,
modules: {
User
}
})
Copy the code
Definition module
@Module
Define a VUex Module using @Module that accepts the following parameters:
attribute |
The data type |
describe |
name |
string
|
The name of the module (if namespace exists) |
namespaced |
boolean
|
Whether the module has a namespace |
stateFactory |
boolean
|
Whether to enable the state factory (for module reuse) |
dynamic |
true
|
If this is a dynamic module (added to storage after storage is created) |
store |
Store |
Store to inject into this module (for dynamic modules) |
preserveState |
boolean
|
If this option is enabled, the state is preserved when the module is loaded |
Create a module with the following syntax:
import { VuexModule } from 'vuex-module-decorators'
@Module({
name: 'User',
namespaced: true,
stateFactory: true
})
export default class User extends VuexModule {
}
Copy the code
Note that the name of the module introduced in the Stroe constructor needs to be the same as the name specified in the decorator, otherwise the corresponding module will not be found
state
The definition of state is similar to that of data in the component:
@Module({
name: 'User',
namespaced: true,
stateFactory: true
})
export default class User extends VuexModule {
token = getToken()
}
Copy the code
The above code has the same effect as the following:
export default {
state:{
token: getToken()
},
namespaced:true
}
Copy the code
@Mutation
Mutation is defined using the @mutation decorator:
@Module({
name: 'User',
namespaced: true,
stateFactory: true
})
export default class User extends VuexModule {
token = getToken()
@Mutation
setToken (token: string) {
this.token = token
token ? setToken(token) : deleteToken()
}
}
Copy the code
@Action
Action is defined using the @Action decorator, which takes three arguments:
Parameter names |
type |
describe |
commit |
string
|
The load submitted |
rawError |
boolean
|
Whether to print the original error type (error messages are wrapped by default) |
root |
boolean
|
Whether root loads are allowed to be submitted |
If no parameter is passed, the load needs to be submitted manually:
@Module({
name: 'User',
namespaced: true,
stateFactory: true
})
export default class User extends VuexModule {
token = getToken()
@Mutation
setToken (token: string) {
this.token = token
token ? setToken(token) : deleteToken()
}
@Action
async login () {
this.context.commit('setToken', 'token')
router.replace('/')
}
}
Copy the code
If the submitted load name is specified, the load value can be set by the return value of the function:
@Module({
name: 'User',
namespaced: true,
stateFactory: true
})
export default class User extends VuexModule {
token = getToken()
@Mutation
setToken (token: string) {
this.token = token
token ? setToken(token) : deleteToken()
}
@Action({commit:'setToken'})
async login ():string {
router.replace('/')
return 'token'
}
}
Copy the code
@MutationAction
MutationAction decorator (@mutationAction) : mutatioin (@mutationAction) : mutatioin (@mutationAction) : MutationAction (@mutationAction) : mutatioin (@mutationAction)
@Module({
name: 'User',
namespaced: true,
stateFactory: true
})
export default class User extends VuexModule {
testStr = ''
@MutationAction({ mutate: ['testStr'] })
async setStr () {
return new Promise<{ testStr: string }>(resolve => {
resolve({
testStr: 'test'
})
})
}
}
Copy the code
Note that the data structure of the returned object must match the specified parameter name
getter
The definition and the Vue getter in the component attribute defines a similar calculation, using the get prior to the method name:
@Module
class MyModule extends VuexModule {
wheels = 2
get axles() {
return this.wheels / 2
}
}
Copy the code
Complete sample
import { deleteRefreshToken, deleteToken, deleteUserInfo, getRefreshToken, getToken, getUserInfo, setRefreshToken, setToken, setUserInfo } from '@/utils/auth' import { UserInfo } from '@/types/user' import router from '@/router' import { Action, Module, Mutation, MutationAction, VuexModule } from 'vuex-module-decorators' @Module({ name: 'User', namespaced: true, stateFactory: true }) export default class User extends VuexModule { token = getToken() refreshToken = getRefreshToken() userInfo: UserInfo | null = getUserInfo() testStr = '' @Mutation setToken (token: string) { this.token = token token ? setToken(token) : deleteToken() } @Mutation setRefreshToken (token: string) { this.refreshToken = token token ? setRefreshToken(token) : deleteRefreshToken() } @Mutation setUserInfo (user: UserInfo | null) { this.userInfo = user user ? setUserInfo(user) : deleteUserInfo() } @MutationAction({ mutate: ['testStr'] }) async setStr () { return new Promise<{ testStr: string }>(resolve => { resolve({ testStr: 'test' }) }) } @Action async login () { this.context.commit('setToken', 'token') this.context.commit('setRefreshToken', 'refreshToken') this.context.commit('setUserInfo', {}) router.replace('/') } @Action async loginOut () { this.context.commit('setToken', '') this.context.commit('setRefreshToken', '') this.context.commit('setUserInfo', null) router.replace('/login') } }Copy the code
Use in components
GetModule (); getModule();
import { Component, Vue } from 'vue-property-decorator'
import User from '@/store/modules/user'
import { getModule } from 'vuex-module-decorators'
let user:User
@Component
export default class test extends Vue {
login ():void {
console.log(user.testStr)
user.login()
}
mounted ():void {
user = getModule(User, this.$store)
}
}
Copy the code
Used in small programs
It’s easy to use TypeScript in applets. Choose TypeScript as the language when creating projects, and the rest are similar to Vue projects
Unlike Vue projects that compile TypeScript automatically, applets need to compile TS files manually, which is a bit of a hassle, so we can use Webstrom to develop applets:
Install the applets plug-in and let Webstrom support applets syntax: File>Setting>Plugins, search for Wechat Mini programs upport, and restart Webstrom.
Set ts files to compile automatically: File>Setting>Languages & Frameworks>TypeScript
conclusion
This series of articles is written in conjunction with the project. If you want to learn more about TypeScript, check out the following sites:
TypeScript Chinese website
TypeScript tutorial
TypeScript learning resources collection
This article may not be comprehensive, incorrect or difficult to understand, feel free to comment in the comments section ๐๐
In the meantime, everyone, spray gently, after all:
I’m a character eight nickname, we’ll see you in other series