天天看點

vue + typescript 踩坑筆記(一)

最近在用 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
        }
    }
複制代碼           

這就是目前碰到的一些小坑吧,在寫項目的過程中參考了以下文章:

  • 從 JavaScript 到 TypeScript
  • TypeScript踩坑(持續更新)
  • typescript 中函數參數為對象的時候怎麼寫

目前還未體會到typescript的強大之處,感覺就是寫的很繁瑣。/(ㄒoㄒ)/~~

轉載于:https://juejin.im/post/5c6fc8e0e51d4574704086c7