自尤大去年9月推出vue對typescript的支持後,一直想開箱嘗試,對於前端sr來講,vue的順滑加上ts的面向對象,想着就很是美好~ 終於在兩個月前,找到了個機會嘗試了一把vue+ts的組合。 開文記錄下vue和ts整合之旅和遇到的一些坑。html
應該大部分人都知道vue,畢竟現在vue是與react肩並肩的存在,因此就不過多介紹啦。前端
vue中文官網 官網上的教程就是最好的入門教程vue
我在前幾篇文章就一直有在宣傳typescript,簡單列舉下ts的優勢node
始於JavaScript,歸於JavaScript,typescript是JavaScript的超集,因此它能夠重用JavaScriptd代碼,使用JavaScript的庫react
JavaScript用的優勢它都有,跨瀏覽器、跨操做系統等webpack
面向對象的編程思想,強大的類型檢查web
開源大法好vuex
要說缺點的話,那就是不太適合過小的項目。vue-cli
就憑這些優勢,足夠咱們愉快的玩耍~typescript
先將node安裝,而後在經過npm安裝ts的包
npm install -g typescript
tsc -v
查看ts的版本號
咱們將經過官方提供的腳手架 vue-cli 來建立項目
npm install -g @vue/cli
安裝完成後,能夠經過 vue create
快速建立一個新項目的腳手架,或者直接經過 vue serve
構建新想法的原型。
vue create vue-ts
vue-ts是咱們的項目名稱,執行後以下可看到有這麼幾個選項,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包
項目結構以下
index.html
入口文件就放在裏面,這個文件夾下的文件不會歸入webpack的打包中;
src:存放vue項目工程文件,其中已經幫咱們關聯好router和vuex,文件結構很是簡潔
其餘:webpack、babel等配置文件
項目在構建中,已經引入 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裏的數據
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() 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('name',{ immediate: true, deep: true })
public onChildChanged(val: string, oldVal: string) {
console.log('watch new name=' + val);
}
複製代碼
public get allname() {
return 'computed ' + this.name;
}
複製代碼
allname是計算後的值,name是被監聽的值
@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是個可選的,因此單獨列出來。首先須要引用 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 })
複製代碼
搭建完成後,就能夠像後端同樣擼前端啦~