最近在用 vue + typescript 寫一個專案,由於是第一次使用typescript,所以踩了一些坑,這裡記錄一下。
一. vue-property-decorator
使用vue-cli搭建專案的話,可以從它給出的Home.vue檔案中,可以看到用typescript寫單vue檔案會有一些不同:
import { Component, Vue } from "vue-property-decorator";
import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src
@Component({
components: {
HelloWorld
}
})
export default class Home extends Vue {}
複製程式碼
-
vue-property-decorator
從示例中看出Component, Vue這些是從vue-property-decorator這個庫引入的,vue-property-decorator是個什麼呢?這是它的GitHub地址vue-property-decorator。
從它的介紹來看,它說這個庫是完全依賴另一個庫vue-class-component推薦先去閱讀這個庫的README,好吧,那隻能先去看看vue-class-component這個庫是什麼了。
在vue的官網中有提到:
我看了一些其他人寫的文章,簡單的說就是用typescript寫vue每次都需要寫一些額外形式的程式碼,vue-class-component通過裝飾器來減少這些重複的程式碼,vue-property-decorator則是在vue-class-component的基礎上增加了一些裝飾器。
-
裝飾器
在寫JavaScript的時候,基本是沒有接觸過裝飾器,還好之前學習Python的時候,接觸到了這方面的知識,簡單介紹下:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' 需求:想要給函式add和函式square增加執行時間列印功能 ''' def add(a, b): return a + b def square(a): return a ** 2 複製程式碼
方法一:直接在add和square執行前和執行後把時間列印出來即可:
import time t1 = time.time() a = add(10, 20) print('add執行時間:%f' % (time.time() - t1)) t2 = time.time() b = square(10) print('square執行時間:%f' % (time.time() - t2)) 複製程式碼
方法二:將重複的程式碼封裝起來
def print_execute_time(func): def wrap(*args, **kwargs): t1 = time.time() result = func(*args, **kwargs) print('%s執行時間:%f' % (func.__name__, time.time() - t1)) return result return wrap print_execute_time(add)(10, 20) print_execute_time(square)(10) 複製程式碼
就是把需要執行的函式當做引數,給需要執行的函式包一層。
方法三:使用裝飾者模式,在Python中是
@裝飾函式名
語法:#!/usr/bin/env python3 # -*- coding: utf-8 -*- import time def print_execute_time(func): def wrap(*args, **kwargs): t1 = time.time() result = func(*args, **kwargs) print('%s執行時間:%f' % (func.__name__, time.time() - t1)) return result return wrap @print_execute_time # 新增 def add(a, b): return a + b @print_execute_time # 新增 def square(a): return a ** 2 add(10, 20) square(10) 複製程式碼
總結下就是,在不改寫函式體或者函式呼叫方式的情況下,給函式增加一些新功能。雖然這是Python的例子,但是概念還是差不多的,JavaScript中呢好像還處於提案階段,具體參考阮一峰大神的修飾器。
既然用了vue-property-decorator,那麼vue的寫法也就出現了一些不同,比如:
import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src @Component({ components: { HelloWorld } }) export default class Home extends Vue {} // data msg = 'hello' name = 'home' // props @Prop({ default: "text" }) type!: string; @Prop() placeholder!: string; // methods say_name(): void { console.log(this.name) } 複製程式碼
好在是vue-property-decorator這個庫給了不同裝飾器的用法示例,可以去GitHub上參考。
-
二. @Prop() private msg!: string;
在看vue-cli給出的示例中,HelloWorld這個元件中,prop的寫法是這樣,發現一個特殊的地方,就是msg後面加了一個!,在typescript中這種寫法的意思就是!前面的這個變數一定不是undefined或者null,!叫非空斷言操作符。文件
三. 當函式的引數是物件的時候
es6中加入瞭解構賦值這一新語法,所以我在寫函式的時候喜歡這樣寫:
const obj = {
name: 'allen',
age: 18
}
function say_something({ name, age }) {
console.log(name, age)
}
複製程式碼
因為typescript中有靜態資料型別這個東西,就是在宣告變數的時候,就要定好該變數的型別,那麼在函式中引數也是需要給它定好一個型別的:
// 一開始我以為只要寫Object就好了, 但是這樣會報錯
const obj: Object = {
name: 'allen',
age: 18
}
function say_something({ name, age }: Object):void {
console.log(name, age)
}
// 後來網上查了一下,需要寫成這樣:
interface obj {
name: string;
age: number;
}
function say_something({ name, age }: obj):void {
console.log(name, age)
}
// 或是這樣:
function say_something({ name, age }: any):void {
console.log(name, age)
}
複製程式碼
四. Element implicitly has an 'any' type because type 'Set' has no index signature
這是一個報錯提示,出現在了我這樣寫的時候:
export default class Test extends Vue {
set_something(name: string, value: any):void {
this[name] = value
}
}
複製程式碼
要解決這個問題,需要這樣寫:
export default class Test extends Vue {
set_something(name: string, value: any):void {
interface IParams {
[key: string]: any
}
(<IParams>this)[name] = value
}
}
複製程式碼
這就是目前碰到的一些小坑吧,在寫專案的過程中參考了以下文章:
目前還未體會到typescript的強大之處,感覺就是寫的很繁瑣。/(ㄒoㄒ)/~~