关于vue.js:无法在带有Typescript的vue中使用Mixins

unable to use Mixins in vue with typescript

我有这样的文件夹结构

1
2
3
4
--Page    
   -group.vue    
--Services
  -groupMixin.ts

group.vue的脚本

1
2
3
4
5
6
7
8
9
10
<script lang="ts">
     import { Vue, Component, Mixins } from 'vue-property-decorator'

     import { GroupMixin } from '../../services/groupMixin';
     @Component
     export default class Group extends Mixins(GroupMixin) {
        created () {
          console.log(this.test)
        }
      }

groupMixin.ts的代码

1
2
3
4
5
import { Vue } from 'vue-property-decorator'
//creating mixins.
export class GroupMixin extends Vue {
  test: string = 'sss'
}

我在这里面临两个问题。

首先,要导入我使用../../的ts文件,有什么方法可以使用./或@ /。 无需使用lang =" ts",我可以导入这样的js文件@ / services / ...

其次,无法访问我在groupmixin.ts中声明的可变测试。


我今天花了很多时间试图弄清楚如何使Vue mixins在TypeScript项目中工作。显然,这些教程说的使用mixins的所有普通方法根本无法在TypeScript中使用。这些组件无权访问其mixin中定义的属性,因为显然Vue框架的mixin代码只是对TypeScript不友好。

最终,我确实找到了一种在TypeScript中使用mixins的方法。实际上工作得很好。我的项目中有多个级别的mixin继承,mixin扩展了其他mixin,并且它们完全按照我的预期工作。秘密是我必须安装有人写的用于修复TypeScript中的mixins的第三方软件包:

https://www.npmjs.com/package/vue-typed-mixins

几句话警告(但没什么大不了的):

  • 仅当我在.ts文件而不是.vue文件中定义我的mixins时,此插件才对我有用。这对我来说不是问题,因为我的mixins仅包含代码,不包含html或css(而且我认为这种情况甚至没有道理)。

  • 当您在组件上包含mixin时,请确保以与软件包网站上的示例相同的方式进行操作(上面的URL)。如果仅安装软件包而不重构代码以遵循网站上的示例,则它将无法正常工作。

  • 这是一个简单的例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // /src/mixins/MyMixin.ts

    import Vue from"vue";

    export default Vue.extend({
        data: function () {
            return {
                mixinMessage:"this came from MyMixin!"
            };
        },
        created: function () {
            console.log("MyMixin.created()");
        },
        mounted: function () {
            console.log("MyMixin.mounted()");
        },
        methods: {
            mixinOutput: function (text:string) {
                console.log("mixin says:" + text);
            }
        }
    });

    然后由以下人员使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    // /src/components/MyComponent.vue

    <template>
       
            whatever
       
    </template>

    <style>
        /* whatever */
    </style>

    <script lang="ts">
        import mixins from"vue-typed-mixins";
        import MyMixin from"../mixins/MyMixin";

        export default mixins(MyMixin).extend({
            created: function () {
                console.log("MyComponent.created()");
            },
            mounted: function () {
                console.log("MyComponent.mounted()");

                this.mixinOutput("hello from MyComponent");
                this.mixinOutput(this.mixinMessage);
            }
        });


    请尝试执行以下操作以使Mixin正常工作:

    组别

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <script lang="ts">
     import Vue from 'vue';
     // mixins only exist in `vue-class-component` and Component is a default export.
     import Component, { mixins } from 'vue-class-component';

     import { GroupMixin } from '../Services/groupMixin';

     @Component
     export default class Group extends mixins(GroupMixin) {
        created () {
          console.log(this.test)
        }
      }

    groupMixin.ts

    1
    2
    3
    4
    5
    import { Vue } from 'vue'

    export class GroupMixin extends Vue {
      test: string = 'sss'
    }

    我之所以使用import Vue from 'vue';导入Vue是有原因的,这主要是因为某些IDE从vue-class-component导入时会突出显示诸如$emit之类的Vue函数。

    至于导入ts文件,如果您不使用vue-cli,则需要设置webpack的resolve别名,并且还需要在tsconfig.json中设置,并且可能需要使用tsconfig-paths


    截至今天,有两种将Typein / Vue使用mixin的方法:

  • 如果您的mixin仅包含变量:
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // mixins/title.ts
    import { Vue, Component } from 'vue-property-decorator'

    @Component
    export default class titleMixin extends Vue {
      public test: string = 'Hello, hello, hello'
    }

    // Page.vue
    import { Component, Vue, Mixins } from 'vue-property-decorator'
    import titleMixin from '@/mixins/title'

    export default class Page extends Mixins(titleMixin) {
      private mounted(): void {
        console.log(this.test) // would print: Hello, hello, hello
      }
    }
  • 如果您使用生命周期挂钩:
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // mixins/title.ts
    import { Vue, Component } from 'vue-property-decorator'

    @Component
    export default class titleMixin extends Vue {
      private mounted(): void {
        console.log('somevalue')
      }
    }

    // Page.vue
    import { Component, Vue } from 'vue-property-decorator'
    import titleMixin from '@/mixins/title'

    @Component({
      mixins: [titleMixin]
    })
    export default class Page extends Vue {} // this will print console.log

    这样对我有用。您可以看一下'vue-class-component'包:https://github.com/vuejs/vue-class-component/blob/master/test/test.ts#L389


    mixins.ts

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import { Vue, Component } from"vue-property-decorator";

    @Component
    export default class Mixin extends Vue {
      public perfectScrollbarSetting: object = {
        maxScrollbarLength: 750
      };
      public widthClient: number = 0;
      public heightClient: number = 0;
    }

    文件About.vue

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <template>
    </template>
    <script lang="ts">
    import { Vue, Component, Mixins } from"vue-property-decorator";
    import { generalInfo } from"../../store/modules/general";
    import Mixin from"../../mixin/mixins";
    @Component({
      mixins: [Mixin]
    })
    export default class About extends Mixins(Mixin) {
      mounted() {
        console.log(this.widthClient) //it's work
      }

    }


    基于@Joe Irby的答案,我发现它在不使用vue类型的mixins的情况下可以工作。

    随着mixin扩展Vue,您可以通过扩展mixin来创建组件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    // MyMixin.ts

    import Vue from"vue";

    export default Vue.extend({
        data: function () {
            return {
                message:"Message from MyMixin!"
            };
        }
    });


    // MyComponent.vue

    <template>
        ...
    </template>

    <script lang="ts">
        import MyMixin from"@/mixins/MyMixin";

        export default MyMixin.extend({
            mounted: function () {
                console.log(this.message);
            }
        });