最近在用 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的時候,接觸到了這方面的知識,簡單介紹下:
方法一:直接在add和square執行前和執行後把時間列印出來即可:#!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' 需求:想要給函數add和函數square增加執行時間列印功能 ''' def add(a, b): return a + b def square(a): return a ** 2 複制代碼
方法二:将重複的代碼封裝起來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中是
文法:@裝飾函數名
總結下就是,在不改寫函數體或者函數調用方式的情況下,給函數增加一些新功能。雖然這是Python的例子,但是概念還是差不多的,JavaScript中呢好像還處于提案階段,具體參考阮一峰大神的修飾器。#!/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) 複制代碼
好在是vue-property-decorator這個庫給了不同裝飾器的用法示例,可以去GitHub上參考。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) } 複制代碼
-
二. @Prop() private msg!: string;
@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
}
}
複制代碼
這就是目前碰到的一些小坑吧,在寫項目的過程中參考了以下文章:
- 從 JavaScript 到 TypeScript
- TypeScript踩坑(持續更新)
- typescript 中函數參數為對象的時候怎麼寫
目前還未體會到typescript的強大之處,感覺就是寫的很繁瑣。/(ㄒoㄒ)/~~
轉載于:https://juejin.im/post/5c6fc8e0e51d4574704086c7