Getting started with ts in vue project

Recently, the project needs to transform the original vue project in combination with the use of ts. this should be the development trend of medium and large-scale projects. I see a good introductory tutorial and expand it a little. This article explains from installation to vue component writing, which is suitable for getting started.

1. Introduce Typescript

npm install vue-class-component vue-property-decorator --save
npm install ts-loader typescript tslint tslint-loader tslint-config-standard --save-dev

vue class component: extend vue to support typescript, and support ts by declaring the original vue syntax

Vue property decorator: extend more decorators based on Vue class component

ts loader: enables webpack to recognize ts files

Tslint loader: tslint is used to constrain file encoding

Tslint config standard: tslint configures standard style constraints

2. Configuration file

webpack configuration
According to the different configurations of different projects, if it is a project created by vue cli 3.0, it needs to be configured in vue.config.js. If it is less than 3.0, it needs to be configured in webpack.base.conf. (the following instructions are changed in the webpack.base.conf file)

1. Add. ts in resolve.extensions to introduce the ts file into the code without writing the. ts suffix

 resolve: {
    extensions: ['.js', '.vue', '.json', '.ts'],
    alias: {}
  }

2. Add ts rules in module.rules

 module: {
    rules: [
      {
        test: /\.ts$/,
        exclude: /node_modules/,
        enforce: 'pre',
        loader: 'tslint-loader'
      },
      {
        test: /\.tsx?$/,
        loader: 'ts-loader',
        exclude: /node_modules/,
        options: {
          appendTsSuffixTo: [/\.vue$/]
        }
      }
    ]
  }

3.tsconfig.json configuration
ts loader will retrieve tsconfig.json in the file and parse the ts file according to the rules therein. For detailed configuration, please refer to https://www.tslang.cn/docs/handbook/tsconfig-json.html
Paste the test project tsconfig.json file

{
  // Compile options
  "compilerOptions": {
    // Output directory
    "outDir": "./output",
    // Does it contain a sourceMap that can be used for debug ging
    "sourceMap": true,
    // Parse in strict mode
    "strict": false,
    // Modular system used
    "module": "esnext",
    // How to handle modules
    "moduleResolution": "node",
    // Compile output target ES version
    "target": "es5",
    // Allow default import from modules that do not have default export set
    "allowSyntheticDefaultImports": true,
    // Treat each file as a separate module
    "isolatedModules": false,
    // Enable decorator
    "experimentalDecorators": true,
    // Enable design type metadata (for reflection)
    "emitDecoratorMetadata": true,
    // An error occurs when there is an implied any type on expressions and declarations
    "noImplicitAny": false,
    // Not all return paths of the function have return values, and an error is reported.
    "noImplicitReturns": true,
    // Import external help libraries from tslib: for example__ extends,__ rest et al
    "importHelpers": true,
    // Print file names during compilation
    "listFiles": true,
    // Remove comment
    "removeComments": true,
    "suppressImplicitAnyIndexErrors": true,
    // Allow javascript files to be compiled
    "allowJs": true,
    // Resolve the base directory of non relative module names
    "baseUrl": "./",
    // Specify the path of the special module
    "paths": {
      "jquery": [
        "node_modules/jquery/dist/jquery"
      ]
    },
    // List of library files to be imported during compilation
    "lib": [
      "dom",
      "es2015",
      "es2015.promise"
    ]
  }
}

4.tslint.json configuration
Add a new tslint.json file in the directory. Since we installed tslint config standard earlier, we can directly use the rules in tslint config standard. The file is as follows:

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

3. Let the item identify.ts

Since TypeScript does not support files with *. Vue suffix by default, a vue-shim.d.ts file needs to be created and placed in the root directory when it is introduced into the Vue project

declare module '*.vue' {
  import Vue from 'vue';
  export default Vue;
}

4. Compilation of vue components

Most methods in vue components are changed to use @ xxx (decorator) to indicate why data is currently defined, similar to injection in ng. The business logic js can be written in ts directly.

Basic writing
The writing method of template and style remains unchanged, and the module of script has been changed. The basic writing method is as follows

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
@Component
export default class Test extends Vue {
  
};
</script>

lang = "ts": the current language under the script declaration is ts
@Component: indicate that this class is a vue component
Export default class test extensions vue: export the current component class inherits vue

Define data in data()

The data in data is defined directly in the object instead of the original data() method

export default class Test extends Vue {
 public message1: string = "heimayu";
 public message2: string = "That's nice";
}

props value transfer

props is not as comfortable as data, because it needs to use decorators. The writing method is as follows

@Prop()
propA:string

@Prop()
propB:number

$emit value transfer

Without parameters

  // Original writing: this.$emit('bindSend ')
  // Now write this.bindSend() directly
  // Multiple definitions
  @Emit()
  bindSend():string{
      return this.message
  }

Method with parameters

  // Original writing: this.$emit('bindSend', msg)
  // Now write directly: this.bindSend(msg)
  // Multiple definitions below
  @Emit()
  bindSend(msg:string){
      // to do something
  }

emit with parameters

  // Test here is to change the @ event name referenced by the component. At this time, @ test should be written instead of @ bindSend2
  @Emit('test)
  private bindSend2(){
      
  }

watch observation data

  // Original writing watch: {}

  @Watch('propA',{
      deep:true
  })
  test(newValue:string,oldValue:string){
      console.log('propA The value has changed' + newValue);
  }

computed calculated attribute

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

Complete code case

<template>
  <div class="test-container">
    {{message}}
    <input type="button" value="Click to trigger the parent method" @click="bindSend"/>
    <input type="button" value="Click to trigger the parent method" @click="handleSend"/>
    <input type="button" value="Click to trigger the parent method" @click="bindSend2"/>
    <!-- <Hello></Hello> -->
  </div>
</template>
<script lang="ts">
import { Component, Prop, Vue, Watch, Emit } from "vue-property-decorator";
import Hello from "./HelloWorld.vue";
// Note that this class is a vue component
@Component({
  components: {
    Hello
  }
})
export default class Test extends Vue {
  // The data in the original data is expanded and written here
 public message: string = "asd";
  //Data expansion and compilation in the original props
  @Prop({
    type: Number,
    default: 1,
    required: false
  })
  propA?: number
  @Prop()
  propB:string
  //Original computed
  public get computedMsg(){
      return 'Here is the calculation attribute' + this.message;
  }
  public set computedMsg(message:string){
  }
  //Original watch attribute
  @Watch('propA',{
      deep:true
  })
  public test(newValue:string,oldValue:string){
      console.log('propA The value has changed' + newValue);
  }
  // In the past, when it was necessary to pass values to the parent, just use emit in the method directly. At present, it needs to be processed through emit
  @Emit()
  private bindSend():string{
      return this.message
  }
  @Emit()
  private bindSend1(msg:string,love:string){
      // If it is not processed, the following can not be written, and the parameters will be returned automatically
    //   msg += 'love';
    //   return msg;
  }
  //The original methods placed in methods are tiled
  public handleSend():void {
      this.bindSend1(this.message,'love');
  }
  // The parameter in emit here indicates what the parent accepts, similar to the previous $emit('parent defined method ')
  @Emit('test')
  private bindSend2(){
      return 'This works test accept';
  }
}
</script>

Tags: Javascript Vue.js Webpack

Posted on Sun, 07 Nov 2021 14:51:34 -0500 by Rithotyn