BonBonSlick
@BonBonSlick
Vanilla Web Architect

Vue + typescript для чего классы и как их использовать?

'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.

и еще больше аналогичных ошибок.

А если убрать конструктор с параметром и попробовать присвоить так
for (let item of items) {
            let menuItem = new Item();
            menuItem.title = item.title;


выдаст ошибку [Vue warn]: Missing required prop: "title"
потому что
@Prop({required: true})

И не понятно зачем тогда классы если приходится делать так
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>
  • Вопрос задан
  • 60 просмотров
Решения вопроса 1
Aetae
@Aetae
Тлен
Ты не понимаешь что происходит.
Декоратор @Component превращает класс в Vue-компонент.
Делая new <name> ты создаёшь не инстанс исходного класса, ты создаёшь инстанс Vue-компонента.
@Component работает только с классам, коструктор которых не принимает никаких параметров(потому что нет никакой возможности на самом деле их передать).
Какие параметры принимает конструктор Vue, смотреть надо здесь.

Условно говоря(на самом деле потроха сложнее), этот код:
@Template
@Component
export default class Item extends Vue {
    @Prop({required: true}) private title!: string;

    private get getter() {}

    private method() {}
        
    constructor(title: string) {
        super();
    }
};
превращается в этот:
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() {}
  }
})

Для чего? Для того чтоб было красивее, всё было в одном месте и тайпинг с наследованием работал.

P.S. На всякий случай: декоратор это просто функция, которая работает с переданными параметрами и тем что стоит после него, возвращая результат преобразования. Никакой магии.
Код:
@Template
@Component({})
export default class Item extends Vue {}
равносилен:
export default Template(
  Component({})(
    class Item extends Vue {}
  )
)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы