教你搭建基於typescript的vue項目

自尤大去年9月推出vue對typescript的支持後,一直想開箱嘗試,對於前端sr來講,vue的順滑加上ts的面向對象,想着就很是美好~ 終於在兩個月前,找到了個機會嘗試了一把vue+ts的組合。 開文記錄下vue和ts整合之旅和遇到的一些坑。html

vue

應該大部分人都知道vue,畢竟現在vue是與react肩並肩的存在,因此就不過多介紹啦。前端

vue中文官網 官網上的教程就是最好的入門教程vue

typescript

我在前幾篇文章就一直有在宣傳typescript,簡單列舉下ts的優勢node

  1. 始於JavaScript,歸於JavaScript,typescript是JavaScript的超集,因此它能夠重用JavaScriptd代碼,使用JavaScript的庫react

  2. JavaScript用的優勢它都有,跨瀏覽器、跨操做系統等webpack

  3. 面向對象的編程思想,強大的類型檢查web

  4. 開源大法好vuex

要說缺點的話,那就是不太適合過小的項目。vue-cli

就憑這些優勢,足夠咱們愉快的玩耍~typescript

ts安裝

先將node安裝,而後在經過npm安裝ts的包

npm install -g typescript

tsc -v 查看ts的版本號

建立項目

咱們將經過官方提供的腳手架 vue-cli 來建立項目

安裝腳手架與建立項目

  1. 執行安裝命令

npm install -g @vue/cli

安裝完成後,能夠經過 vue create 快速建立一個新項目的腳手架,或者直接經過 vue serve 構建新想法的原型。

  1. 建立項目 vue create vue-ts vue-ts是咱們的項目名稱,執行後以下

vue-create

可看到有這麼幾個選項,xiaoli這個選項是我以前建立的,稍後會介紹;default這個後面寫着 babel eslint ,表示若選擇這個,那麼只會引入babel和 ealint;manually select features顧名思義,選擇咱們想要的。那麼咱們選擇第三個

可看到列表裏有不少選項,咱們以vue+ts爲主,因此咱們選擇 babel typescript router vuex 這幾個,選擇完後,以下

接下來會有好幾個yes or no 的選項,你們根據本身項目的須要來選擇就能夠,最後一步,Save this as a preset for future projects? 若選擇yes,就會將咱們以前的選擇存儲起來,做爲一個預設選項,方便後續一鍵建立新項目。全部步驟選完,回車,便開始建立項目文件結構和拉取npm包

項目結構

項目結構以下

public: 用於存放靜態文件, index.html入口文件就放在裏面,這個文件夾下的文件不會歸入webpack的打包中;

src:存放vue項目工程文件,其中已經幫咱們關聯好router和vuex,文件結構很是簡潔

其餘:webpack、babel等配置文件

與typescript服用

項目在構建中,已經引入 vue-class-component ,用於對ts的支持,或者使用 vue-property-decorator,這個庫是在以前那個的基礎上擴展。

如下列舉tsvue寫法的各類變化

組件聲明

建立組件的方式變成以下

import { Component, Prop, Vue, Watch } from 'vue-property-decorator';

@Component
export default class Test extends Vue {

}
複製代碼

data對象

經過構造函數建立data裏的數據

import { Component, Prop, Vue, Watch } from 'vue-property-decorator';

@Component
export default class Test extends Vue {
    private name: string;
    constructor() {
        super();
        this.name = 'xiaoli';
    }
}
複製代碼

data裏的數據使用方式以下

public getName(){
    return this.name
}
複製代碼

Prop聲明

@Prop() public msg: string;
@Prop({ default: 'default value' }) propB: string
@Prop([String, Boolean]) propC: string | boolean
複製代碼

生命週期函數使用

public created(): void {
    console.log('created');
}

public mounted():void{
    console.log('mounted')
}
複製代碼

自定義方法

js下是須要在method對象中聲明方法,現變成以下

public clickFunc(): void {
    console.log(this.name)
    console.log(this.msg)
}
複製代碼

Watch監聽屬性

@Watch('name',{ immediate: true, deep: true })
public onChildChanged(val: string, oldVal: string) {
    console.log('watch new name=' + val);
}
複製代碼

computed計算屬性

public get allname() {
    return 'computed ' + this.name;
}
複製代碼

allname是計算後的值,name是被監聽的值

emit事件

@Emit()
  addToCount(n: number) {
    this.count += n
  }

  @Emit('reset')
  resetCount() {
    this.count = 0
  }
複製代碼

第一個的事件名稱爲 add-to-count,n爲傳過去的參數;第二個事件名爲reset-count,參數爲空

指令和過濾器

----------小小更新一下---------------

有小夥伴問指令和過濾器在ts下的寫法,以前給遺漏了,如今補充一下。

我嘗試了下,發現以前在入口文件直接引入指令或者過濾器的方式無論用了,由於用了ts後,組件的做用域跟以前的不同了,而後我找了官方的issue,截圖以下

在做者在4月11號回覆裏,認可了這個問題,但具體何時將指令和過濾器的聲明加上就未知了,不過做者在issue中給出瞭解決方案。我寫個簡單的小栗子

一個自定義指令

// ./directive/index.ts
export const focus = {
    // 當被綁定的元素插入到 DOM 中時……
    inserted: function (el:HTMLElement) {
        // 聚焦元素
        el.focus()
      }
}
複製代碼

一個過濾器

// ./filter/index.ts
export const capitalize = function (value:string) {
    if (!value) return ''
    value = value.toString()
    return value.charAt(0).toUpperCase() + value.slice(1)
}
複製代碼

組件中使用

import { capitalize }from '@/filter/index'
import { focus } from '@/directive/index'
@Component({
    filters:{capitalize},
    directives:{focus}
})
export default class Test extends Vue {}
複製代碼
<div>
    <input v-focus v-model="modelData">
    <div>{{modelData | capitalize}}</div>
</div>
複製代碼

可看出這是局部引用,全局引用目前還沒找到辦法,歡迎有解決辦法的小夥伴指教~

vuex與ts的糅合

由於vuex是個可選的,因此單獨列出來。首先須要引用 vuex-class 庫,該庫有以下幾個模塊

import {
    namespace,
    Action,
    Getter,
    Mutation,
    State
} from 'vuex-class';
複製代碼

分別對應vuex中的 action、getter、mutation等,使用ts對vuex的影響主要在組件對vuex的調用上,vuex的定義仍是按照以前的寫法便可

@State('foo') stateFoo
@State(state => state.bar) stateBar
@Getter('foo') getterFoo
@Action('foo') actionFoo
@Mutation('foo') mutationFoo
@someModule.Getter('foo') moduleGetterFoo

// If the argument is omitted, use the property name
// for each state/getter/action/mutation type
@State foo
@Getter bar
@Action baz
@Mutation qux
複製代碼

若不想使用vuex定義的方法名,能夠自定義屬性名,由於都是定義在當前this上,因此直接使用this調用便可

this.getterFoo // -> store.getters.foo
this.actionFoo({ value: true }) // -> store.dispatch('foo', { value: true })
複製代碼

小結

搭建完成後,就能夠像後端同樣擼前端啦~

相關文章
相關標籤/搜索