带Typescript的Nuxt,似乎“Vue.extend”不支持插入的数据

nvbavucw  于 2023-04-12  发布在  Vue.js
关注(0)|答案(4)|浏览(219)

我正在尝试在我的Nuxt项目上提供打字脚本支持。
我知道在返回组件数据时必须使用Vue.extend,如下所示:

import Vue from 'vue';

type Data = {
 a: number
}

export default Vue.extend({
 data():Data{
  const a = 3;
  return {
   a
  }
 }
})

但是,如果我的组件有注入的属性,它不会将这些属性附加到this类型。

import Vue from 'vue';

type Data = {
 a: number
}

export default Vue.extend({
 
 inject: ['b'],
 
 data():Data{
  const a = 3;
  const c = this.b
            ^^^^
            // ~~ Property 'b' does not exist on type 'Readonly<Record<never,any>> & Vue' 
  return {
   a
  },
 
  methods:{
   my_method(){
     this.a // no problem here
     this.b // Error here
   }
  }

 }
})

不应该也推断出注入类型吗?
我被迫用途:

const that = this as any;

我想避免的事

pdsfdshx

pdsfdshx1#

您可以尝试在data方法中显式键入this

import Vue from 'vue';

type Data = {
  a: number
}

export default Vue.extend({

  inject: ['b'],

  data(this: { b: string }): Data {
    const a = 3;
    const c = this.b
    return {
      a
    }
  },

  methods: {
    my_method() {
      this.a // no problem here
      this.b // ok
    }
  }
})

Playground
你可以看看Vue.extends类型定义:

export interface VueConstructor<V extends Vue = Vue> {
  new <Data = object, Methods = object, Computed = object, PropNames extends string = never>(options?: ThisTypedComponentOptionsWithArrayProps<V, Data, Methods, Computed, PropNames>): CombinedVueInstance<V, Data, Methods, Computed, Record<PropNames, any>>;
  // ideally, the return type should just contain Props, not Record<keyof Props, any>. But TS requires to have Base constructors with the same return type.
  new <Data = object, Methods = object, Computed = object, Props = object>(options?: ThisTypedComponentOptionsWithRecordProps<V, Data, Methods, Computed, Props>): CombinedVueInstance<V, Data, Methods, Computed, Record<keyof Props, any>>;
  new (options?: ComponentOptions<V>): CombinedVueInstance<V, object, object, object, Record<keyof object, any>>;

// we are interested in first
  extend<Data, Methods, Computed, PropNames extends string = never>(options?: ThisTypedComponentOptionsWithArrayProps<V, Data, Methods, Computed, PropNames>): ExtendedVue<V, Data, Methods, Computed, Record<PropNames, any>>;



 // ......
  extend<Data, Methods, Computed, Props>(options?: ThisTypedComponentOptionsWithRecordProps<V, Data, Methods, Computed, Props>): ExtendedVue<V, Data, Methods, Computed, Props>;
  extend<PropNames extends string = never>(definition: FunctionalComponentOptions<Record<PropNames, any>, PropNames[]>): ExtendedVue<V, {}, {}, {}, Record<PropNames, any>>;
  extend<Props>(definition: FunctionalComponentOptions<Props, RecordPropsDefinition<Props>>): ExtendedVue<V, {}, {}, {}, Props>;
  extend(options?: ComponentOptions<V>): ExtendedVue<V, {}, {}, {}, {}>;
}

因此,您可以提供显式泛型:

export default Vue.extend<Data, { my_method: () => void }, object, 'b'>({

  inject: ['b'],

  data(): Data {
    const a = 3;
    const c = this.b
    return {
      a
    }
  },

  methods: {
    my_method() {
      this.a // no problem here
      this.b // ok
    }
  }
})
sh7euo9m

sh7euo9m2#

使用vue-class-componentvue-property-decorator
通过使用这些库,您可以编写像这样的强大的类型脚本代码。

@Component({
  layout: 'form',
  head: { title: 'somr title' },
  directives: { onlyNumber: onlyNumberDirective }
})
export default class Login extends Vue {
  @Ref()
  readonly form!: HTMLFormElement;
  
  phone = '';
  password = '';
  
  someMethod() {}

  get someComputedVar() {}
}

nuxt-property-decorator也合并上述库,使其更简单。

ybzsozfc

ybzsozfc3#

我也遇到了这种情况,这是我找到的解决方案:你应该像下面这样为nuxt写一个插件,并将其添加到插件部分的nuxt.config中。
所以对于第一个创建对象,Vue.extend

export const MyService = Vue.extend({

  data(){
    return {
      ready: false
    }
  },

  watch: {
    '$accessor.auth.loggedIn'(success){
        if (!success) return;

         this.ready = true;
        //do something here ...
     }
  },

  methods: {
    //...
  },

  
})

然后导出configure plugin函数如下:

export default function (ctx, inject) {

  const hookMixin = {
    created() {
      // nuxt context depends on $root object,
      // so here we assigning $root which just created

      const $root = this.$root;
      const myService = new MyService({
        beforeCreate() {
          this.$root = $root;
        }
      });

    //make $myService accessible globally
    Object.defineProperty(Vue.prototype, '$myService', {
      get() { return myService; }
    })

    },
  }

  // here adding global hook onMounted as mixin
  const mixins = ctx.app.mixins || [];
  mixins.push(hookMixin);
  ctx.app.mixins = mixins;
}

这里有三个步骤,你应该这样做,这个组件是全球可用的。
1.为nuxt注册created一个钩子,等待nuxt准备就绪。
1.当组件在beforeCreate准备就绪时,分配nuxt $root对象,您可以通过VueContructor options设置。
1.使服务全局化,以便通过Object. defineProperty通过$myService进行访问。
在这个例子中,我使用了存储变量loggedIn的watch。这里我也使用了typed-vuex,所以$accessor是一个全局访问器。逻辑很简单,我等待用户登录,然后我做一些事情。
享受您的定制组件!

gg0vcinb

gg0vcinb4#

Nuxt3吗?
一定要换

import Vue from 'vue'
export default Vue.extend({...})

import { defineComponent } from 'vue';
export default defineComponent({ ... })

相关问题