current position:Home>Experience summary of typescript transformation process of old vue2.x projects

Experience summary of typescript transformation process of old vue2.x projects

2022-06-24 08:28:01Army Zhou

Preface :

About Vue2.x Of TS reform , There's nothing to say .

about vue-cli For projects , Run it all over again  vue create xxx-project , choice Manually select features , Choose again typescript Options can be . Or directly vue add typescript Can also be .

Too much information on the Internet , I also recommend some that I think are OK ( I made it myself , I don't think it's hard , ha-ha )

about webpack, It's just adding ts-loader, Then increase tsconfig.json, To configure ts attribute , And then eslint increase ts Code specification . Then go and change the old project file to ts file , Just fine . Just one sentence ^_^, After all, today it's all 2021 了 ( After all TS It's been popular for years ), There are so many tutorials .

Project configuration considerations :

This article talks about some matters needing attention , And the similarities and differences of some implementation methods , And my point of view ( Please leave a message before it goes wrong , Thank you very much )

WebPack Configuration modification

  • increase TS suffix :extensions: ['.js', '.vue', '.json', '.ts'], 
  • increase ts-loader: {test: /\.ts$/, loader: 'ts-loader', exclude: /node_modules/, options: {appendTsSuffixTo: [/\.vue$/],}}

TypeScript The configuration file

Project root creation tsconfig.json file , Note the following configuration :

  • "strictPropertyInitialization": false, // strict The default is true—— You have to make sure that the properties of each instance are initialized
  • "noImplicitAny": false, // false Means to run an implicit any type , That is, no type is allowed to be set , This setting runs js The document was changed directly to ts file
  •  "allowJs": true, // Initial transformation , Must be JS And TS Parallel run
  • "strictFunctionTypes": false, // Enable vuex-class You need to turn on this option
  • "target": "es5", // Compile output target ES edition
  • "skipLibCheck": true,
  •  "jsx": "preserve", //  stay .tsx The document supports JSX
  • "experimentalDecorators": true,  // Enable decorator
  •  "strictNullChecks": true, // When you declare a variable , It does not automatically contain null or undefined.

Other , Just follow the official order .

Want to noImplicitAny It's just a comparison of the way chicken thieves play , But you have a transformation of an old project , You can change and adjust . Otherwise , Change... Change , You'll lose confidence .

eslint Parsing rules add TS Configuration item

The root directory ,.eslintrc.js, Reference configuration

extends: [
  'plugin:vue/recommended',
  'eslint:recommended',
  '@vue/typescript/recommended',
  '@vue/prettier',
  '@vue/prettier/@typescript-eslint'
],
parserOptions: {
  ecmaVersion: 2020,
},

In fact, this configuration , Let's see if you like . Default vue-cli The generated file is good , No, vue-cli Generate a demo project ,copy One copy . Of course, we have to comply with the goose factory's internal code specifications , Don't stick .

TypeScript The statement of

Official documents :https://www.tslang.cn/docs/handbook/declaration-files/introduction.html

import Vue, { VNode } from 'vue';
declare global {
  interface Window { //  Global variables 
    i18n: any;
    eCharts: any;
  }
}
declare module 'vue/types/vue' {
  interface Vue {
    $bus: Vue;
    $route: any;
    $router: any;
    CancelToken: any;
    $message: any;
    $confirm: any;
  }
}
declare global {
  namespace JSX {
    interface Element extends VNode {}
    interface ElementClass extends Vue {}
    interface IntrinsicElements { [elem: string]: any; }
  }
}

This is the end of the project

TS Some precautions

This part is just for the transformation , Things to remind members of

TS type

any

any, It's easy to use , however , If you let it go completely , believe me , It's most likely that in the end any

But at the beginning of the project , You can use first any displacement , There's time in the back , In further refinement . This measure , It's not a very good measure . For novice , When code merges , Or call back any.

Optional attribute vs null undefined

null and undefined yes ts The basic types in , Each has a value null and undefined, By default, they are subtypes of all types , That is, it can be assigned to any type .

null And undefined Is a valid value for all other types . It also means that , You can't stop assigning them to other types , Even if you want to stop it . null The inventor of the ,Tony Hoare, Call it a billion dollar mistake .

tsconfig.js Set in file strictNullChecks by true when , Can not be null and undefined Assign values to other than themselves and void Any type other than .

Under the circumstances of such strict inspection , If you really want to set the initial value to be null for a value of another type somewhere , And then assign a value , You can use union types to achieve .

let test: string | null = 'hi'

null and undefined It's different

string|undefined、string|null and string|undefined|null There are three different types .

If set "strictNullChecks": true, Optional parameters will be added automatically |undefined

let test?: string = 'hi'

interface/class/abstract class/type

Declaration Type

Namespace

Type

Value

Namespace

X

X

Class

X

X

Enum

X

X

Interface

X

Type Alias

X

Function

X

Variable

X

not symbol,js There is 6 Basic types ,number,string,boolean,null, undefined, object. But only depending on these types , To describe what kind of parameters a function needs to pass , It's not enough , This is also interface The mission of -- Describe a value (value) The shape of the (type).

class First of all, it also has interface The ability of , Describe a shape , Or it represents a type . Besides class It also provides implementation , That is to say, it can be instantiated ;

interface Sure extends class, At this time class Take on a type of role . Here's what I wrote before java I mean , somewhat WTF. In fact, for undefined It has its own type called undefined,java The programmer also said that he was confused .

TypeScript Through the use of structured type system to reflect JavaScript The dynamic characteristics of , And very good at type inference , It means you don't have to be like C# or Java That's how to express the type . TypeScript One of the design goals of is not to create a “ The right type system ”, It is “ Strike a balance between correctness and productivity ”.——TypeScript The compiler doesn't force you to declare types , The degree of type safety is up to you . You can even decide to apply different levels of type security rigor to different areas of the project . This flexibility is not what traditional statically typed languages can offer .

It's not like talking too much here , Think typescript The manual is very detailed :https://www.tslang.cn/docs/handbook/basic-types.html

Vue Upgrade scheme comparison

vue2 Upgrade to TS There are many kinds of transformation schemes .

Traditional scheme :vue-property-decorator

vue2 Yes ts Our support is mainly through vue class component. It depends mainly on decorators . By the way, Amway 《 from java The notes ramble on typescript Decorator —— Annotations and ornaments 》.

Besides , We can expand our understanding of metaprogramming .

vue2 What is more criticized is that ts Support for , Yes ts Poor support is vue2 An important reason for not being suitable for large projects . The fundamental reason is that Vue Rely on a single this Context to expose properties , also vue Medium this Than in the ordinary javascript More magical ( Such as methods Object method Medium this It doesn't point to methods, It's pointing to vue example ). let me put it another way , You dada is designing Option API I didn't think about it ts Reference support )

The specific usage is quite detailed :https://github.com/kaorun343/vue-property-decorator

<template>
  <div>
    <sidebar/>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator';
import { Action, Mutation, State } from 'vuex-class';
import sidebar from 'layout/sidebar';
@Component({
  components: {
    sidebar,
  },
})

export default class App extends Vue {
  private loading = true

  @State(state => state.user.theme)
  private readonly theme
  @Mutation('user/setThemeModel')
  private setThemeModel
  @Action('user/getUserInfo')
  private getUserInfo

  @Watch('$route.params.id')
  private handler() {
    // TODO
  }

  private get testCount() {
    // TODO
  }

  private mounted(): void {
  }
}
</script>

I don't like this style very much , however , But it's used all around , Now the refactoring project adopts this style

typescript mixin

I am right. mixin Not very cold . Now that we need to use it , Be sure to pay attention to the following points :

mixins The law of merger :
  • Covered :data,props,methods,computed,inject
  • Direct replacement :el,template,propData
  • Consolidated :
    • methods, The function with high weight is executed first
    • Life cycle function ,watch Listen for callback functions , Small weight Execute first
mixins Mix weights

similar css Weight rule ( In fact, there is no weight , But the result is the same , I just think it's easy to understand )

  • *、 overall situation Options
  • 1、...... Omit innumerable possible nesting mixin
  • 10、 Components - mixin - mixin
  • 100、 Components - mixin
  • 1000、 Component options

See more about 《vue mixins、Vue.extend() 、extends Use notes

It's easy to use

import { Component, Mixins, Vue } from 'vue-property-decorator';
// mixin
@Component
export default class PageLeave extends Vue {
  // TODO
}
//  Components 
@Component({
  components: {
    TitleBar,
  },
})
export default class CardPanel extends Mixins(PageLeave,OtherMixin) {
  //TODO
}

however TS Of vue project ,mixin Basically excluded by me .

As early as 2016 Mid term , Dan · Abramov (Dan Abramov) Just write it 《mixin Considered harmful 》(mixin Considered Harmful), He argues in the book that , take mixin Used in React Reuse logic in components is an anti pattern , Stand away from them . What he mentioned about React mixins The same is true of Vue.

OPP It could have solved everything , Is it not fragrant !

vue-property-decorator Program drawback

  • vue class component And js Of vue Components are too different , In addition, additional libraries need to be introduced , The cost of learning has increased dramatically .
  • Depending on the decorator Syntax . At present, the decorator is still in stage2 Stage ( You can see tc39 decorators), There is still a lot of uncertainty in the implementation details , This makes it a rather dangerous base .
  • Complexity increases . use Vue Class Component And you need to use additional libraries , Compared with simple js vue Components , Obviously complicated .

I'm more inclined to the next plan .

tsx Combination plan :Vue Components + TypeScript

I started out writing react Of , Post write vue, So I prefer this style

import Vue, { VueConstructor, CreateElement, VNode } from 'vue';
interface InputInstance extends Vue {
  composing: boolean;
}
export default (Vue as VueConstructor<InputInstance>).extend({
  name: 'demo-input',
  props: {},
  data() {},
  // TODO  more Vue Like other components 
  render(h: CreateElement): VNode {
    // TODO  Logic 
    const classes = []
    const wrapperAttrs = {...this.$attrs};
    const wrapperEvents = {...this.$listeners};
    // JSX  grammar 
    return (
      <div class={classes} {...{ attrs: wrapperAttrs, on: wrapperEvents }}>
        <input/>
      </div>
      );
  }
}

there mixin It's the same as before

// Count.mixin.ts
import Vue from 'vue'
import { mapGetters } from 'vuex'
export default Vue.mixin({
  computed: {
    ...mapGetters(['count'])
  },
  methods: {}
})
// Count.vue
export default Vue.extend<{}, Methods, Computed, {}>({
  mixins: [CountMixin],
  methods: {}
})

Multiple mixin blend

import CountMixin, { Computed as CountComputed } from './Count.mixin'
import LoadingMixin, { Computed as LoadingComputed } from './Loading.mixin'
type Computed = CountComputed & LoadingComputed
interface Methods {
  incrementCount: Function
  decrementCount: Function
}
export default Vue.extend<{}, Methods, Computed, {}>({
  mixins: [CountMixin, LoadingMixin],
  methods: {}
})

however , above mixin Of data type Paste the ……

Recommended implementation
interface CountBindings extends Vue {
  count: number
}
export default (Vue as VueConstructor<CountBindings>).extend({
  mixins: [CountMixin],
  methods: {}
})

Please refer to ,https://medium.com/glovo-engineering/vue-components-typescript-ff62db05829c

composition-api

This first needs npm i -S @vue/composition-api

And then global Injection

import VueCompositionApi from "@vue/composition-api";
Vue.use(VueCompositionApi);

Actually , I'm also thinking about this . I'll supplement this later .

Upgrade directly Vue3.0

I don't know how to do it , If it's rewriting refactoring , I will definitely use it directly Vue3.0. But for big projects , Refactoring directly uses 3.0, Or fear .

Although you da da said vue2 And vue3, Don't like angular2 So different from their descendants , however , I'd better slow down first

Vuex Store Pain

stay ts It uses vuex It's very painful .

vuex ts Version related vuex-class and vuex-module-decorators The two libraries should be the most used at present ( Personally think that ).

https://www.npmtrends.com/vuex-aggregate-vs-vuex-class-vs-vuex-module-decorators

stars

issues

updated

created

vuex-class

1,653

18

Oct 12, 2020

Jan 14, 2017

vuex-module-decorators

1,595

123

May 8, 2021

May 1, 2018

If it's an old project , I recommend you use it first vuex-class excessive .

I'll sort it out here for the time being , Go to bed early on the weekend . Follow up and follow up ……

Reprint This station article 《vue2.x Old projects typescript Summary of experience in the transformation process 》, Please indicate the source :https://www.zhoulujun.cn/html/webfront/ECMAScript/vue/8637.html

copyright notice
author[Army Zhou],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/175/20210625231856804w.html

Random recommended