Getting started with TypeScript (integration with VUE2)

install

install

npm install -g typescript

Open project folder

tsc -init

compile

tsc ts01.ts

Listening and compiling

tsc -w

Listen and compile a file

tsc -w ts01.ts

Modify the location and target syntax of the compiled JS

Open tsconfig JSON, modify the value of outDir and uncomment it

{
  "compilerOptions": {
    "target": "es3",
    "outDir": "./js/"
  }
}

It will be converted to ES6 by default. It is recommended to convert to ES3 or ES5 to be compatible with most browsers.

grammar

data type

let num: number = 1;
let str: string = "hello";
let b: boolean = true;
let n: null = null;
let un: undefined = undefined;
let f: any = 1;
// Get type
console.log("typeof(str):"+typeof(str))
// array
let arr1: Array<number> = [1, 2, 3];
let arr2: number[] = [1, 2, 3];
let arr3: string[] = ["aa", "bb", "cc"];
let arr4: Array<number | string> = [1, "aa", 3];
// tuple
let tup: [string, string, number] = ['Dylan', 'male', 23];
console.log("typeof(tup):"+typeof(tup))

What is the difference between arrays and tuples?

A tuple can be understood as an array with a fixed length and each element type determined.

Let's look at an example

let tup: [string, string, number] = ['Dylan', 'male', 23];
tup.push("123");
tup[3] = 123;

Example 2

let tup: [string, string, number] = ['Dylan', 'male', 23];
tup.pop();
tup[2] = 456;

In this example, we can find several problems with tuples:

  1. Although the length is fixed, we can push the element so that its length exceeds the defined length without error. However, the subscript value cannot exceed the defined length.
  2. If the push exceeds the length, the converted js can run normally, and the print result also contains elements exceeding the length, so it is not recommended to add elements through push, but set them through subscript.
  3. When push ing, the data type can be the type included in the definition, and cannot be other types.
  4. When assigning values according to subscripts, the type must be the same as when defining.
  5. After pop deletes elements, we can still assign values through subscripts.

class

Implementation of interface class integration and method overloading of interface class

interface Person { 
  run():void;
}

class Men implements Person { 
  name: string;
  age: number;

  constructor(name:string,age:number) { 
    this.name = name;
    this.age = age;
  }
  run(): void {
    console.log("run");
  }

  talk(): void;
  talk(str:string): void;
  talk(num:number): void;
  talk(str:string,num:number): void;
  talk(par1?:any,par2?:any) {
    if (par1 == undefined && par2 == undefined) {
      console.log("method 1");
    }
    else if (par2 == undefined) {
      if (typeof par1 == "string") {
        console.log("method 2");
      }
      else if (typeof par1 == "number") {
        console.log("method 3");
      }
    } else { 
      console.log("method 4");
    }
  }
}

class SuperMen extends Men{

}

let men = new Men("Xiao Ming", 18);
men.talk();
men.talk("Xiao Ming");
men.talk(18);
men.talk("Xiao Ming",18);

The results can be seen

method 1
method 2
method 3
method 4

VUE2 integrated TS

When creating a new project, you can directly select ts. this is mainly about the upgrading of old projects.

Installation dependency

npm i vue-class-component vue-property-decorator --save
npm i ts-loader typescript tslint tslint-loader tslint-config-standard -D

Configure Vue config. JS add the following code

module.exports = {
  configureWebpack: {
    resolve: { extensions: [".ts", ".tsx", ".js", ".json"] },
    module: {
      rules: [
        {
          test: /\.ts$/,
          exclude: /node_modules/,
          enforce: 'pre',
          loader: 'tslint-loader'
        },
        {
          test: /\.tsx?$/,
          loader: 'ts-loader',
          exclude: /node_modules/,
          options: {
            appendTsSuffixTo: [/\.vue$/],
          }
        }
      ]
    }
  },
}

New tsconfig JSON is placed in the project root directory

{
  "compilerOptions": {
    "allowJs": true,
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "baseUrl": ".",
    "types": [
      "webpack-env"
    ],
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

Add two TS files in the src root directory

shims-tsx.d.ts

// shims-tsx. d. TS SRC directory
import Vue, { VNode } from 'vue';
declare global {
  namespace JSX {
    // tslint:disable no-empty-interface
    interface Element extends VNode {}
    // tslint:disable no-empty-interface
    interface ElementClass extends Vue {}
    interface IntrinsicElements {
      [elem: string]: any;
    }
  }
}

Create a new hips Vue d.ts

// shims-vue. d. TS SRC directory
declare module '*.vue' {
  import Vue from 'vue';
  export default Vue;
}

//Adaptation definition file for TypeScript because vue file is not a regular file type,
//TypeScript cannot understand what vue files are for. This paragraph is added to tell TypeScript that vue files are of this type.
//Without this file, you will find all the files imported by import vue files will report errors.
//axios error
declare module 'axios' {
  interface AxiosInstance {
    (config: AxiosRequestConfig): Promise<any>
  }
}

Add tslint json

{
  "extends": "tslint-config-standard",
  "globals": {
    "require": true
  }
}

main.js to main TS configure Vue config. JS entry is main ts

pages: {
    index: {
      entry: 'src/main.ts',
    }
  },

Install @ typescript eslint / parser

Change the eslint check to @ typescript eslint / parser

npm install @typescript-eslint/parser --save

Change eslintrc.js

parserOptions: {
  parser: '@typescript-eslint/parser'
},

Code format

Comparison of old and new writing methods

Original writing

<script>
  export default {
    name: 'xx',// Component name
    components: {},// assembly
    props: {},// Value passed from parent component
    data() { // attribute
      return {};
    },
    computed:{}, // Calculation properties
    watch:{},// monitor
    mounted() {}, // Life cycle hook function
    methods: {} // method
  };
</script>

New writing (TS)

<template>
  <div class="home">
    <HelloWorld :msg="message" />
    {{ computedMsg }}
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch, Emit } from "vue-property-decorator";
import HelloWorld from "@/components/HelloWorld.vue";

@Component({
  components: {
    HelloWorld,
  },
})
export default class Home extends Vue {
  // props
  @Prop({
    type: Number,
    default: 1,
    required: false,
  })
  propA?: number;

  @Prop()
  propB?: string;

  // data
  public message = "Hello TS";

  // computed
  public get computedMsg(): string {
    return "Here is the calculation attribute" + this.message;
  }

  // watch property
  @Watch("propA", {
    deep: true,
  })
  public test(newValue: string, oldValue: string): void {
    console.log("propA The value has changed" + newValue + " oldValue:" + oldValue);
  }

  // $emit
  // Original writing: this$ emit('mysend',this.message)
  // Now write this directly bindSend()
  @Emit("mysend")
  bindSend(): string {
    return this.message;
  }

  // mounted lifecycle hook function
  mounted(): void {
    console.info("mounted");
    this.mymethod();
  }

  // Methods in methods
  public mymethod(): void {
    this.bindSend();
  }
}
</script>

$emit

contrast

count = 0
// this.count += n; this.$emit('add-to-count', n)
@Emit("add-to-count")
addToCount(n: number) {
  this.count += n;
}

// this.count = 0; this.$emit('reset');
@Emit("reset")
resetCount() {
  this.count = 0;
}

// this.$emit('return-value', 10)
@Emit('return-value')
returnValue() {
  return 10;
}

// Equivalent to this$ emit('on-input-change', num+1, num)
@Emit("on-input-change")
onInputChange(num: number) {
  return num + 1;
}

// amount to
// const promise = new Promise((resolve) => {
//   setTimeout(() => {
//     resolve(20)
//   }, 0)
// })
//
// promise.then((value) => {
//   this.$emit('promise', value)
// })
@Emit()
promise() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(20);
    }, 0);
  });
}

As can be seen from the above example

Unless the alias of the $emit method is set. The return value of the method is $emit, the second parameter. The parameter passed by the method is the third parameter of $emit. If the method has no return value, it is the second parameter. The execution order is to execute the code in the method body first, and then $emit.

Added by elgordo1960 on Wed, 02 Mar 2022 03:40:38 +0200