18

我有这样的文件夹结构

--Page    
   -group.vue    
--Services
  -groupMixin.ts

group.vue 的脚本

<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)
        }
      }
</script>

groupMixin.ts 的代码

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

我在这里面临两个问题。

首先,要导入我使用../../的ts文件,有没有办法使用./或@/。在不使用 lang="ts" 的情况下,我可以导入这样的 js 文件 @/services/...

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

4

8 回答 8

18

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

最终,我确实找到了一种让 mixin 在 TypeScript 中工作的方法。事实上,工作得很好。我的项目中有多个级别的 mixin 继承,mixin 扩展了其他 mixin,这一切都完全按照我的预期工作。秘诀是我必须安装这个第三方包,有人写它来修复 TypeScript 中的 mixins:

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

几句警告(但都不是什么大不了的事):

  1. 只有当我在 .ts 文件而不是 .vue 文件中定义我的 mixin 时,这个插件才对我有用。这对我来说不是问题,因为我的 mixin 只包含代码,没有 html 或 css(我想不出这种情况甚至有意义)。

  2. 当您在组件中包含 mixin 时,请确保您按照与包网站上的示例相同的方式进行操作(上面的 url)。如果您只是安装包而不重构代码以遵循站点上的示例,它将无法工作。

这是一个简单的例子:

// /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);
        }
    }
});

然后由以下人员使用:

// /src/components/MyComponent.vue

<template>
    <div>
        whatever
    </div>
</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);
        }
    });
</script>
于 2019-01-20T04:52:56.890 回答
11

请尝试执行以下操作以使您的 mixin 正常工作:

组.vue

<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)
    }
  }
</script>

groupMixin.ts

import { Vue } from 'vue'

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

我使用 importing Vueusing是有原因的,import Vue from 'vue';主要是因为某些 IDE 突出显示 Vue 功能,例如$emitvue-class-component.

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

于 2018-08-16T09:47:24.623 回答
9

根据@Joe Irby 的回答,我发现它在没有 vue-typed-mixins 的情况下也可以工作。

当你的 mixin 扩展了 Vue 时,你可以通过扩展你的 mixin 来创建你的组件:

// 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);
        }
    });
</script>
于 2020-03-23T14:52:39.230 回答
8

到今天为止,有两种方法可以在 Typescript/Vue 中使用 mixin:

  1. 如果你的 mixin 只包含变量:
// 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. 如果您使用生命周期挂钩:
// 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

于 2019-05-14T10:32:02.870 回答
6

mixins.ts

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

<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
  }

}
</script>
于 2019-07-17T06:08:37.180 回答
4

如果你不使用 vue-class-component (目前我不是因为它不能很好地与 setup/composition api 配合使用)你可以使用 defineComponent 作为 mixin 并且它在 vue 3 和 typescript 中工作

混合示例:

yor_mixin.ts

import {defineComponent} from "vue"

interface MixinState{
    lastScrollPosition: number;
}

export default defineComponent({
    data(): MixinState{
        return {
            lastScrollPosition: 0,
        }
    },
    methods:{
        scrollDisable(){
            document.body.style.overflow = "hidden";
            this.lastScrollPosition = window.pageYOffset;
        },
        scrollEnable(){
            document.body.style.overflow = "auto";
            window.scrollTo(0, this.lastScrollPosition)
        }
    }
})

和组件


<script lang="ts">
import {computed, defineComponent} from 'vue';
import {useStore, MUTATIONS} from "@/store";
import scrollDisableMixin from "@/mixins/scrollDisable";

export default defineComponent({
  mixins: [scrollDisableMixin],

  setup(){
    const store = useStore();
    return {
      expanded: computed(() => store.state.menu.expanded),
      toggle: () => store.commit(MUTATIONS.TOGGLE_MENU_MAIN),
    }
  },

  watch: {
    expanded: function(){
      this.expanded ? this.scrollDisable() :this.scrollEnable();
    }
  }

})
于 2021-04-23T11:26:10.303 回答
0

这个答案适用于愿意使用vue-class-component(装饰器)的人......你要做的就是从'vue-class-component'导入选项并在那里添加你的mixin。

脚步:

1-创建你的混音:在这个例子中,我创建一个混音来格式化时间(HH:MM:ss)

//Mixin
 export default {
   methods: {
     formatTime(date: string) {
       return new Date(date)
         .toTimeString()
         .replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1");
     },
   },
 };

2-通过将其添加到选项装饰器中来使用组件中的mixin。

   //Home.vue

    import { Options, Vue } from "vue-class-component";

    import formatTimeMixin from '../mixin/formatTime';

    <template>
       <h1> Time left: {{formatTime(timeLeft)}} </h1>
    </template>

    @Options({
      mixins: [formatTimeMixin],
    })
    export default class Home extends Vue {
       timeLeft = 10000;
    }

就是这样,希望这可以帮助那里的人!

于 2021-08-15T11:54:41.443 回答
0

作为 mixins 的缺点,为什么不尝试对 Vue3 的设置进行 mixins 的重构: https ://codesandbox.io/s/delicate-sea-0xmim?file=/src/components/HelloWorld.vue:2262-2495 Comp。 Vue

export default {
  name: "HelloWorld",
  setup() {
    const { test } = useGroup();
    console.log(test);
    return Object.assign({}, useGroup());
  },
  mounted() {
    this.compRef = this;
  },
  props: {
    msg: String,
  },
};

使用Group.js

import { ref, nextTick, onMounted } from "vue";

export default () => {
  const compRef = ref(null);
  const test = "Hello World!";

  onMounted(() => {
    nextTick(() => {
      if (compRef.value) {
        const vm = compRef.value;
        console.log(vm.$el, vm.msg);
      }
    });
  });
  return {
    test,
    compRef
  };
};
于 2021-05-21T07:19:39.733 回答