Vue 在 typeScript 中寫mixins。


前言

有個項目,需要使用 mixins 來管理一些通用方法。同時該項目使用 Typescript。

問題

編譯器報錯,提示組件中沒有該 mixin 中的內容。具體看一下代碼。

MixinA:

export const MixinA = {
    method: {
        sayHello() {
            // ...
        }
    }
}

component:

export default Vue.extend({
    mixins: [MixinA],
    create() {
        this.sayHello();   // <- 報錯位置.
    }
})

報錯:

Property 'sayHello' does not exist on type 'CombinedVueInstance<Vue, unknown, unknown, unknown, Readonly<Record<never, any>>>'.Vetur(2339)

根據報錯信息,可以看到是 Vetur 這個插件報的錯。
究其原因,還是因為 TypeScript 不夠聰明,沒法知道 Mixin 到底是什么樣的。

解決方案

這里有許許多多種,我收集整理一下。

  1. 簡單粗暴法 (as 強制轉換) 極度不推薦

    跟着上面的內容:

    (this as any).sayHello();
    

    報錯消失,但是這樣會讓代碼很臟,組件閱讀性差的同時,還要寫很多 as 轉換,同時,轉換 any 讓 typeScript 的意義盪然無存,還不如不用。

  2. 繼承 mixins (只適合當個 mixin)

    mixinA:

    export const MixinA = Vue.extend({
        method: {
            sayHello() {
                // ...
            }
        }
    })
    

    components:

    export default MixinA.extend({
        mixins: [MixinA],
        create() {
            this.sayHello();
        }
    })
    

    也不報錯了,通過繼承 mixinA 的方式,讓編譯器知道里面有什么東西。

    缺點:違背 mixins 的設計初衷,mixins 本身就支持多 mixin 混入。

    優點:簡單粗暴。

  3. 使用 vue-typed-mixins

    import Vue from 'vue'
    import mixins from 'vue-typed-mixins'
    
    const mixinsA = Vue.extend({
    data() {
        return {
        foo: 'test'
        }
    }
    })
    
    const mixinsB = Vue.extend({
    data() {
        return {
        bar: 123
        }
    }
    })
    
    const App = mixins(mixinsA, mixinsB).extend({
    data() {
        return {
        value: true
        }
    },
    
    computed: {
        concat(): string {
        return `${this.foo} ${this.bar} ${this.value}`
        }
    }
    })
    

    優點:可以混合,多個 mixin
    缺點:使用習慣的修改。 還是比較支持的。

  4. 升級為 Vue3。
    Vue 官方在 3 后,有為 mixin 做的處理。(具體沒有了解過,雖然很吐槽這種升級的方式)

  5. 遵循 Vue 和 TS 原則的一種解決方式.

    mixinA :

    
    // mixinA.vue
    導出默認 Vue.extend({…})
    

    mixinB:

    // mixinB.vue
    導出默認 Vue.extend({…})
    

    那么使用這兩個的組件可以定義為:

    export default (Vue as VueConstructor<Vue & InstanceType<typeof MixinA>& InstanceType<typeof
    MixinB>>).extend({
    mixins: [MixinA, MixinB],
    
    
  6. 自己寫接口

    interface mixinState {
    sayHello: () => {}
    }
    
    export default (Vue as VueConstructor<Vue & mixinState>).extend({
    name: 'Home',
    create() {
        this.sayHello();
    }
    })
    
    

    本質上與 第 5 種 是一樣的。
    缺點:要寫許多接口。

  7. 使用 vue-property-decorator 等。

    使用類型注解的方式。沒研究,不喜歡這種寫法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM