国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Vue with typescript

JerryWangSAP / 2678人閱讀

摘要:想要使用語法的話,配合,這個插件,體驗更佳,這個插件在語法中實現了。這種方式最接近的單文件組件的寫法,如果一個完善項目從改成,用這種方法很快,只要加上和一些必要的變量類型就好了,然后用包裹就好。不推薦混入用這種方式寫,無法實現多繼承。

最近嘗試了一下 TypeScript,試著把一個 Vue 項目改成了 TypeScript 的,感覺還不錯 目前 Vue 和 TypeScript 的配合還不算很完美,Vuex 和 TypeScript 的配合挺糟糕的,嘗試需要謹慎 如果想體驗一下的話,強烈建議你用 vue-cli 3 直接生成項目目錄,這樣會少挺多配置,比如配 tsconfig 什么的,在用 vue-cli 的時候選擇 TypeScript 就好

如果想自己體驗從 0 開始配置請參考這個文檔 TypeScript-Vue-Starter

初始配置

這里不提初始配置,因為 vue-cli 已經默認配置好了,在根目錄下,有個 tsconfig.json 的文件,在 src 的文件夾下面,有 shims-tsx.d.ts, shims-vue.d.ts 文件

shims-vue.d.ts 這個文件,主要用于 TypeScript 識別.vue 文件,Ts 默認并不支持導入 vue 文件,這個文件告訴 ts 導入.vue 文件都按VueConstructor處理,因此導入 vue 文件必須寫.vue 后綴,但是這樣同樣的也會造成,就算你寫的導入的 .vue 文件的路徑就算是錯的,靜態檢測也不會檢測到錯誤,如果你把鼠標放上面你會看到錯誤的路徑就是指向這個文件,因為你定義了這個模塊是所有 .vue 后綴的導入都會指向到這個文件,但是如果你的路徑是對的,ts 能讀出正確的 module。
說那么多可能沒用,看一下下面兩張圖就懂了

導入地址是正確的
導入地址是錯誤的

shims-tsx.d.ts 文件,這個文件主要是方便你使用在 ts 中使用 jsx 語法的,如果不使用 jsx 語法,可以無視這個,但是強烈建議使用 jsx 語法,畢竟模板是沒法獲得靜態類型提示的,當然,如果你境界高的話,直接用 vue render function。想要使用 jsx 語法的話,配合 babel-plugin-jsx-v-model,這個插件,體驗更佳,這個插件在 jsx 語法中實現了 v-model。

編輯器支持

推薦使用 Visual Studio Code 和 Vetur 插件,如果用的是 IDE,推薦使用 WebStorm

使用 TypeScript 編寫 Vue 的時候,主要有兩種方法Vue.extend()vue-class-component

Vue.extend():使用基礎 Vue 構造器,創建一個“子類”。 這種方式最接近 Vue 的單文件組件的寫法,如果一個完善 Vue 項目從 JS 改成 TS,用這種方法很快,只要加上 lang=ts和一些必要的變量類型就好了,然后用Vue.extend()包裹就好。請看下面的例子:
JavaScript

TypeScript

vue-class-component:通常和vue-property-decorator一起搭配使用,實際使用只使用vue-property-decorator就好了,vue-property-decorator是在vue-class-component上擴展來的,并且提供了很多修飾器比如 @Prop@Watch等等,使用這個可以編寫類式組件,但是如果你是完善的項目 JS 改 TS 的話,需要改的地方很多。看一下下面的例子:
JavaScript

TypeScript

可以看出變化真的很大

這兩種編寫方式風格有很大的不同,下面具體說一下兩種方式的具體實現

組件 props

Vue.extend()實現 props 其實和 JavaScript 沒有任何差別,但是如果你需要有 Object 變量類型提示,那就有點不一樣了

vue-class-component實現 props, 需要從 vue-property-decorator 引入 Prop 這個修飾符,使用起來也非常方便,還是用上面的例子

      // JavaScript
      props: ["isVisible", "title", "item", "count", "items"]
      // 如果加入了prop驗證,這樣寫
      props: {
        isVisible: {
          type: Boolean,
          required: true
        },
        title: {
          type: [String, Number]
        },
        item: {
          type: Object
        },
        items: {
          type: Array,
        }
        count: {
          count: Number
        }
      }

      // TypeScript
      /* 這種寫法沒有任何改變,但是這樣沒有任何類型提示,這些變量能被TS識別,但是會全部被識別成any,和沒類型檢查一樣 */
      props: ["isVisible", "title", "item", "count", "items"]
      /* 當加入prop驗證之后,TS就會提示prop類型了,如果是對象的話,還能有對象的成員提示,寫法和JS寫法差不多,只是對象類型(包括對象,數組和函數)的有點差別,這樣寫的話。*/
      // 假設item對象的結構是
      interface Item {
        key: string
        val: string
        num: number
      }
      props: {
        isVisible: {
          type: Boolean,
          required: true
        },
        title: {
          type: [String, Number]
        },
        item: {
          // 注意這里不是
          // Object as Item
          type: Object as () => Item
        },
        itmes: {
          // 注意這里不是
          // Array as Array
          type: Array as () => Array
        }
        count: {
          count: Number
        }
      }

      // vue-class-component方式
      import { Vue, Component, Prop } from "vue-property-decorator"

      // 注意要加非空斷言符 ! 不然會報,當然,你定義成any類型當我沒說
      /* [non-null-assertion-operator](https://github.com/Microsoft/TypeScript/wiki
      /What"s-new-in-TypeScript#non-null-assertion-operator) 關于非空斷言可以參考這個 */
      @Prop({
        required: true
      }) isVisible!: boolean
      @Prop() title!: string | number
      @Prop() item!: Item
      @Prop() items!: Array
      @Prop() count!: number

組件 data computed methods watch

Vue.extend()實現 data 其實和 JavaScript 沒有任何差別,computed 的話,也沒什么大的改變,但是有 this 參與運算的必須標明返回值類型,不然會報錯, methods 的處理方式和 computed 的一樣,有 this 參與運算的必須標明返回值類型,watch 也是一樣

vue-class-component實現 data 的話,直接在類里面寫變量就好,computed 的話,寫法類似 getter 和 setter,methods 處理方式就是直接在里面寫方法,watch 需要從 vue-property-decorator 引入 Watch 這個修飾符

      //一個簡單的例子
      // Vue.extend()
      import Vue from "vue"
      export default Vue.extend({
        data() {
          return {
            count: 1,
            item: {
              c: "",
              n: ""
            }
          }
        },
        computed: {
          // 需要標注有 `this` 參與運算的返回值類型
          num(): number {
            return this.count
          },
          name: {
            // 需要標注有 `this` 參與運算的返回值類型
            get(): string {
              return this.item.n
            },
            set(val: string) {
              this.item.n = val
            }
          }
        },
        watch: {
          count(newVal: number, oldVal: number): void {
            console.log(newVal)
          },
          "item.n"(newVal: string, oldVal: string): void {
            console.log(newVal)
          },
          item: {
            handler(newV, oldVal) {
              console.log(oldVal)
            },
            deep: true
          }
        },
        methods: {
          reset(): void {
            this.$emit("reset")
          },
          getKey(): string {
            return this.item.c
          }
        }
      })
    // vue-class-component
    import { Vue, Component, Watch } from "vue-property-decorator"

    interface KeyValue {
      c: string
      n: string
    }

    @Component
    export default class Test extends Vue {
      // data
      count: number = 1
      item: KeyValue = {
        c: "",
        n: ""
      }

      // computed
      get num(): number {
        return this.count
      }
      get name(): string {
        return this.item.n
      }
      // 注意,這里不能標返回值類型,就算寫void也不行
      set name(val: string) {
        this.item.n = val
      }

      // watch
      @Watch("count")
      watchCount(newVal: number, oldVal: number): void {
        console.log(newVal)
      }
      @Watch("item.n")
      watchName(newVal: string, oldVal: string): void {
        console.log(newVal)
      }
      @Watch("item", { deep: true })
      watchItem(newVal: KeyValue, oldVal: KeyValue): void {
        console.log(newVal)
      }
      // methods
      reset(): void {
        this.$emit("reset")
      },
      getKey(): string {
        return this.item.c
      }
    }

組件 components

Vue.extend() components 和 JavaScript 寫法完全一致

vue-class-component 需要把導入的組件寫在修飾器@Components({})里面

      // Vue.extend
      import Vue from "vue"
      import MainHeader from "./header.vue"
      import MainContent from "./content.vue"

      export default Vue.extend({
        components: {
          MainHeader,
          MainContent
        }
      })

      // vue-class-component
      import { Vue, Component } from "vue-property-decorator"
      import MainHeader from "./header.vue"
      import MainContent from "./content.vue"

      @Component({
        components: {
          MainHeader,
          MainContent
        }
      })
      export default class extends Vue {}

組件 mixins

Vue.extend() 并不能完全實現 mixins 多混入的效果,只能混入一個。不推薦混入用這種方式寫,無法實現多繼承。如果你非要嘗試這種寫法,可以看看這個Issue,我沒有嘗試過這種寫法,不過有人寫了個例子,可以作為參考,但是我嘗試了沒成功

// ExampleMixin.vue
export default Vue.extend({
  data () {
    return {
      testValue: "test"
    }
  }
})

// other.vue
export default Vue.extend({
  mixins: [ExampleMixin],
  created () {
    this.testValue // error, testValue 不存在!
  }
})
我們需要稍作修改:

// other.vue
export default ExampleMixin.extend({
  mixins: [ExampleMixin],
  created () {
    this.testValue // 編譯通過
  }
})

vue-class-component 能夠實現多混入,寫法類似類繼承

  // mixin1.ts
  import Vue from "vue"

  export default Vue.extend({
    data () {
      return {
        valFromMixin1: "test"
      }
    }
  })
  // 不能是
  // 這種寫法會報 Mixin1 is not a constructor function type
  export default {
    data () {
      return {
        valFromMixin1: "test"
      }
    }
  }

  // mixin2.ts
  import { Component, Vue } from "vue-property-decorator"

  @Component
  export default class Mixin2 extends Vue {
    methodFromMixin2() {}
  }

  // test.ts
  import Mixin1 from "./mixin1"
  import Mixin2 from "./mixin2"
  import { Component, Mixins } from "vue-property-decorator"

  export default class Test extends Mixins(Mixin1, Mixin2) {
    test() {
      this.methodFromMixin2()
      console.log(this.valFromMixin1)
    }
  }
  // 如果只混入一個的話,可以這樣寫
  export default class Test extends Mixin1 {}
  export default class Test extends Mixin2 {}

這樣寫不僅不會報錯,而且編輯器還有提示

這張圖可以看出,setWatch 是 BookingWatcher 里面的方法,實際上,Test 這個類并沒有自身的屬性,都是從 Vue,BookingWatcher 還有 TestMixins 繼承過來的

函數式組件

這個只能用 Vue.extends(),Vue-class-component 無能為力,可以看看這個 Issue
這里提供一個函數式組件的例子

這部分資料參考

在 Vue 中使用 TypeScript 的一些思考(實踐)
vue 官網 TypeScript 支持

開發中遇到的一些問題總結

$refs 報錯
$refs 報錯這個問題相信基本都遇到,除非你真沒用到這個,如圖:

報錯信息是
Property "blur" does not exist on type "Vue | Element | Vue[] | Element[]".
Property "blur" does not exist on type "Vue".

解決方案:把上圖報錯部分改成

// 把這個變量改成定義成HTMLInputElement就好,這里需要用到類型斷言
test() {
  let inputBox: HTMLInputElement = this.$refs.inputBox as HTMLInputElement
   inputBox.blur()
}

如果引用的比較多,并且引用里面有自己的組件的話,可以這樣寫:
$refs: {}

這樣編輯器還會提示組件里面有什么方法,當你打出 this.$refs.header.時候,編輯器有提示 Header 這個組件里面的屬性和方法

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98790.html

相關文章

  • vue + typescript 項目起手式

    摘要:新項目起手式最后更新于,技術文具有時效性,請知悉我知道你們早就想用上強類型了還有后續進階篇安裝安裝依賴配置添加添加讓識別改造文件什么是是的強類型版本。是的超集,這意味著他支持所有的語法。與此同時,也是的超集,的也宣布采用進行開發。 vue + typescript 新項目起手式 最后更新于2018-06-30,技術文具有時效性,請知悉 我知道你們早就想用上 vue + ts 強類型...

    zhisheng 評論0 收藏0
  • Vue + TypeScript + Element 項目實踐(簡潔時尚博客網站)及踩坑記

    摘要:前言本文講解如何在項目中使用來搭建并開發項目,并在此過程中踩過的坑。具有類型系統,且是的超集,在年勢頭迅猛,可謂遍地開花。年將會更加普及,能夠熟練掌握,并使用開發過項目,將更加成為前端開發者的優勢。 showImg(https://segmentfault.com/img/remote/1460000018720573); 前言 本文講解如何在 Vue 項目中使用 TypeScript...

    luckyyulin 評論0 收藏0
  • Vue Cli3 創建項目

    摘要:創建項目安裝創建一個項目默認套餐,提供和支持。自己去選擇需要的功能,提供更多的特性選擇。比如如果想要支持,就應該選擇這一項。支持使用書寫源碼。支持代碼風格檢查和格式化。 Vue Cli3 創建項目 Vue,Markdown 1. 安裝 npm install -g @vue/cli 2. 創建一個項目 vue create iview-admin # OR vue ui showIm...

    lifefriend_007 評論0 收藏0
  • FCC 成都社區·前端周刊 第 6 期

    摘要:詳情發布新版本中可以自動修復和合并沖突的文件,還新增了命令。詳情是一個用構建設計系統的開源工具,提供了一套基礎應用程序開發的工具,模式和實踐。目前,只有和的最新版本支持該屬性。詳情每周一同步更新到歡迎 01. JS 引擎 V8 v6.6 的更新 最新 v6.6 版本的 V8 JavaScript 引擎更新了方法 Function.prototype.toString(),改進了代碼緩存...

    Airy 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<