使用typescript構建Vue應用

使用typescript構建Vue應用

1、Vue項目初始化-引入typescript

使用typescript構建Vue應用和使用js同樣,都是經過vue-cli去初始化並建立一個vue項目,只不過使用typescript構建的時候 要在腳手架問卷操做的時候勾選上typescript選項

2、typescript Vue項目比較

使用typescript構建的Vue項目發生了一些變化:
main.js變成了main.ts,可是main.ts中的內容和main.js的內容是如出一轍的
router.js變成了router.ts,可是router.ts中的內容和router.js中的內容也是如出一轍的
store.js變成了store.ts,可是store.ts中的內容和store.ts中的內容也是如出一轍的javascript

由於typescript是javascript的超集,因此 ts徹底兼容js

新增了一個shims-vue.d.ts聲明文件,這個文件的做用就是讓typescript可以識別.vue文件,在引入"*.vue"文件的時候,會將其標識爲一個Vue組件,才能對.vue文件進行類型校驗,其具體內容以下:html

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

新增了一個shims-tsx.d.ts文件,其做用就是爲了可以解析.tsx文件,對.tsx文件進行類型校驗,其具體內容以下:vue

import Vue, { VNode } from 'vue'
declare global {
  namespace JSX {
    interface Element extends VNode {}
    interface ElementClass extends Vue {}
    interface IntrinsicElements {
      [elem: string]: any
    }
  }
}

固然還會新增一個ts.config文件,這個是typescript的配置文件,具體內容這裏不做解釋,請參考tsconfig文件詳解java

3、.vue文件內容格式與寫法

使用typescript來寫Vue應用,最主要的就是.vue文件,.vue文件寫法上與js有些不一樣而且 新增了一些裝飾器,接着一步一步分析。

雖然.vue文件的格式和寫法上有了不一樣,但這不一樣只是<script></script>部分發生了變化,<template></template>和<style></style>和原來是同樣的,一個最簡單.vue文件仍然可使用以下寫法:
// HelloWorld.vuevuex

<template>
    <div>
        hello world
    </div>
</template>

在寫<script></script>部分,第一點不一樣就是,<script>標籤上要加上lang語言屬性,表示其中的內容爲ts,如:vue-cli

<script lang="ts">
</script>

默認export上的不一樣,使用js的時候,咱們是直接經過export default {}導出一個Vue組件對象便可,可是使用ts的時候,咱們必須導出一個類class,類名爲組件名,同時這個類必須繼承Vue,如:typescript

// import Vue from "vue";
import { Component, Vue } from 'vue-property-decorator'; // 引入Vue及一些裝飾器
@Component
export default class App extends Vue { // 繼承Vue並導出Vue組件

}
以上就是<sciprt>內容最基本的寫法,上面繼承的Vue不是直接從"vue"模塊中引入,而是從"vue-property-decorator"即vue屬性裝飾器模塊中引入,固然 也能夠經過vue模塊引入import Vue from "vue",可是咱們寫.vue文件的時候 一般要引入一些裝飾器,同時 這個裝飾器類vue-property-decorator也提供了Vue,故能夠直接從vue-property-decorator裝飾器類上直接引入

組件中data屬性的寫法,因爲咱們在.vue文件中聲明瞭一個class,這個class就是Vue組件,咱們能夠直接在這個class中聲明屬性便可,這些聲明的屬性就是以前使用js寫時的data屬性中的數據,如:json

export default class App extends Vue {
  public lists = [ // 這裏就是以前Vue組件的data屬性
    "Vue.js", "React.js", "Angular.js"
  ]
}

組件中的computed計算屬性的寫法,一樣咱們能夠在class中聲明get和set方法便可變成對應的computed屬性,如:數據結構

export default class App extends Vue {
  public lists = [ // 這裏就是以前Vue組件的data屬性
    "Vue.js", "React.js", "Angular.js"
  ]
  public get count() { // 經過get和set實現計算屬性
    return this.lists.length;
  }
}

組件中方法的聲明更簡單,直接在class中聲明方法便可,如:ui

export default class App extends Vue {
    public say() {
        console.log("say");
    }
}

@Component裝飾器的使用,@Component裝飾器就是用來標識當前這個類是一個Vue組件,@Component裝飾器還能夠傳遞對象做爲參數,這個傳遞的對象就是Vue組件實例,因此全部以前用js寫法的時候,Vue組件支持的全部選項均可以傳入,如:

@Component({
    // 這裏能夠配置Vue組件支持的各類選項
    components: {
        HelloWorld
    },
    data() {
        return {
          a:1
        }
    },
    methods: {
        say(){
          console.log("say");
        }
    }
})
export default class App extends Vue {
}
@Component內容使用的是 Vue.extend()方法,用於擴展Vue Component並生成Vue組件,這裏須要注意的就是, Vue最終會將class中定義的屬性和@Component中定義的屬性進行合併,若是兩者中定義了同名的屬性,那麼 class中的優先級更高,即class中定義的會覆蓋掉@Component中定義的同名屬性,可是 data除外@Component中定義的同名的data數據會覆蓋掉class中定義的同名data屬性,如:
@Component({
    data() {
        bar: 1
    },
    methods: {
        say(){
          console.log("say::@Component");
        }
    }
})
export default class App extends Vue {
    public bar: number = 2; // 這裏的bar會被@Component中定義的bar覆蓋掉
    public say() { // 這裏的say()方法會覆蓋掉@Component中定義的say方法
        console.log("say::class");
    }
}
還有一點要注意的是, @Component裝飾器千萬不要漏寫,必須在組件類class前修飾

props屬性的寫法,使用ts寫Vue組件的時候,若是要在組件上定義props屬性,那麼必須經過@Prop()裝飾器,其實就是在定義組件data屬性的時候用@Prop()裝飾器進行修飾,若是沒有經過@Propp()進行修飾,那麼定義的屬性就是組件的data屬性能夠給@Prop()傳遞一個配置對象,能夠定義傳遞屬性的default、required、type等屬性,如:

import { Component, Vue, Prop } from 'vue-property-decorator';
@Component // 不要忘了用@Component修飾組件class喲
export default class HelloWorld extends Vue {
    @Prop() public bar!: string; // 這裏定義的是props屬性
    public foo = "foo"; // 這裏定義的是data屬性
    @Prop({type: String, default:"foo", required: true}) public foo!: string;
}
</script>
須要注意的是,public foo!: string, 這裏聲明的string類型是不起做用的,要限定父組件傳入的foo屬性的數據類型, 必須在@Prop()裝飾器內限定數據類型,不然無效

@Emit()裝飾器的使用,在子組件發射自定義事件的時候一般會經過this.$emit("say")的方式,可是typescript提供了一個@Emit()裝飾器,用於修飾一個方法,當這個方法被執行的時候,就會在方法執行完成後發射一個同方法名的事件出去,固然,這是在沒有給@Emit()傳遞參數的狀況下,若是給@Emit()傳遞了參數,那麼就會發射指定參數的事件,如:

export default class HelloWorld extends Vue {
    @Emit()  // 在say()方法執行完成後會發射一個同方法名的say事件
    public say() {
    }
    @Emit("speak")  // 這裏給@Emit()傳遞了參數,則會發射speak事件
    public say() {
    }
}

@Watch()裝飾器的使用,其擁有監聽組件中數據的變化,就至關於$watch,須要給其傳遞一個字符串參數,表示其監聽的是哪一個數據的變化,如:

@Watch("foo") // 監聽this.foo的變化
public add(newValue: number, oldValue: number) {
  console.log(`newValue is ${newValue}, oldValue is ${oldValue}`);
}

4、vuex中的變化

vuex中的數據是存放在state屬性上的,若是要限定state中數據的屬性和類型,那麼咱們必須在建立store對象的時候定義一個接口限定一下數據類型,如:

interface IState {
  lists: string[]
}
export default new Vuex.Store<IState>({
    state: {
       lists: ["vue"] // 定義了state的數據結構,必需要有lists屬性,而且屬性值爲string[]
    }
});
獲取vuex中的數據時候, 仍是能夠經過this.$store.state.lists獲取到,可是咱們也能夠經過裝飾器獲取到,要使用 vuex的裝飾器,咱們須要安裝 vuex-class,如:
import {State, Mutation, Action} from "vuex-class";
export default class App extends Vue {
    // 將從vuex中獲取到的lists數據保存到組件的lists屬性上
    @State("lists") public lists!: string[];
    @Mutation("say") // 在say()方法前修飾,當say()方法執行的時候就會提交一個say mutation
    public say() {
      console.log("say1");
    }
    @Action("speak") // 在speak()方法前修飾,當speak()方法執行的時候就會提交一個speak action
    public speak(){
    }
    public mounted () {
      this.say();
      this.speak();
    }
}
相關文章
相關標籤/搜索