B
B
BonBon Slick2020-05-24 14:20:59
typescript
BonBon Slick, 2020-05-24 14:20:59

Vue + typescript what are classes for and how to use them?

'use strict';

import {Component, Prop, Vue} from "vue-property-decorator";
import * as Template          from './_template.html?style=./_styles.scss'

@Template
@Component<Item>
export default class Item extends Vue {
    @Prop({required: true}) private title!: string;

    constructor(title: string) {
        super();
        this.title = title;
    }
};
export default class Menu extends Vue {
    private menuItems: Item[] = [];

    public constructor() {
        super();

        const items: { title: string }[] = [
            {
                title: 'Close',
            },
        ];
        for (let item of items) {
            let menuItem = new Item('');
            menuItem.title = item.title;
            this.menuItems.push(menuItem);
        }
    }

TS2322: Type 'typeof Item' is not assignable to type 'VueConstructor<Vue> | AsyncComponentPromise<any, any, any, any> | AsyncComponentFactory<any, any, any, any> | FunctionalComponentOptions<...> | ComponentOptions<...>'.
  Type 'typeof Item' is not assignable to type 'VueConstructor<Vue>'.
    Types of parameters 'title' and 'options' are incompatible.
      Type 'ThisTypedComponentOptionsWithArrayProps<Vue, any, any, any, any> | undefined' is not assignable to type 'string'.
        Type 'undefined' is not assignable to type 'string'.
TS1238: Unable to resolve signature of class decorator when called as an expression.
  Type 'FunctionalComponentOptions<Record<string, any>, PropsDefinition<Record<string, any>>>' is not assignable to type 'void | typeof Item'.
    Type 'FunctionalComponentOptions<Record<string, any>, PropsDefinition<Record<string, any>>>' is missing the following properties from type 'typeof Item': prototype, extend, nextTick, set, and 11 more.

and many more similar errors.

And if you remove the constructor with a parameter and try to assign it like this
for (let item of items) {
            let menuItem = new Item();
            menuItem.title = item.title;


will give an error [Vue warn]: Missing required prop: "title"
because
@Prop({required: true})

And it is not clear why then the classes if you have to do this
export default class Menu extends Vue {
    private isMenuClosed: boolean = true;
    private menuItems: { title: string }[] = [ // хотя мы выводим эти данные в Item::class
            {
                title: 'Close',
            },
            {
                title: 'Login',
            },
        ];

<router-link :key="item.title"
                         :to="{ name:  'test' }"
                         v-for="item in this.menuItems"
            >
                                <item  :title="item.title"  ></item>
            </router-link>

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Aetae, 2020-05-24
@BonBonSlick

You don't understand what's going on.
The decorator @Componentturns the class into a Vue component.
By doing new <name>you are not instantiating the original class, you are instantiating the Vue component.
@Componentonly works with classes whose constructor does not take any parameters (because there is no way to actually pass them).
What parameters the Vue constructor takes, see here .
Relatively speaking (in fact, the offal is more complicated), this code:

@Template
@Component
export default class Item extends Vue {
    @Prop({required: true}) private title!: string;

    private get getter() {}

    private method() {}
        
    constructor(title: string) {
        super();
    }
};
turns into this:
class Item extends Vue {
  constructor() {
    super();
  }
};

export default Vue.extend({
  template: '<содержимое ./_template.html>',
  props: {
    title: {
      type: String, // только при emitDecoratorMetadata
      required: true
    }
  },
  data: () => new Item(),
  methods: {
    method() {}
  },
  computed: {
    getter() {}
  }
})

For what? In order to make it more beautiful, everything was in one place and typing with inheritance worked.
PS Just in case: the decorator is just a function that works with the passed parameters and what comes after it, returning the result of the transformation. No magic.
The code:
@Template
@Component({})
export default class Item extends Vue {}
is equivalent to:
export default Template(
  Component({})(
    class Item extends Vue {}
  )
)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question