Я использую vuejs с машинописным шрифтом и vue-class-component. Я пытаюсь создать пользовательский компонент с реактивными данными.

Вот мой код:

<template>
    <div>
        <input v-model="data.name" placeholder="Name">
        <input v-model="data.value" placeholder="Value">
    </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';

interface Model {
    name: string;
    value: number;
}
@Component
export default class ClubVue extends Vue {
    private data: Model;

    public mounted() {
        this.data = {...this.$store.getters.data};
    }
}
</script>

В этой первой версии я получил эту ошибку:

Свойство или метод "data" не определены в экземпляре, но на них ссылаются во время рендеринга

Это нормально, как сказано на странице компонента vue-class, неопределенные данные не будут отражать. Мне нужно инициализировать данные на ноль. Кроме того, я получаю эту ошибку машинописи:

Свойство 'data' не имеет инициализатора и не определено в конструкторе

Итак, я хочу сделать это:

private data: Model = null;

Но я получаю эту ошибку машинописи:

Тип 'null' нельзя назначить типу 'Model'.

Я не хочу менять тип данных на Model | null, потому что мне придется проверять, являются ли данные нулевыми везде, я буду их использовать, и я знаю, что данные никогда не будут нулевыми.

private data!: Model;

Также не работает, потому что данные будут неопределенными и поэтому не будут реагировать.

Я не хочу отключать проверки машинописи, потому что они полезны для других частей кода.

Есть ли правильный способ инициализации данных здесь?

7
jaudo 16 Апр 2019 в 22:08

2 ответа

Лучший ответ

Правильный тип для такого свойства:

private data: Model | null = null;

Может использоваться с охранниками типа:

if (this.data) {
  console.log(this.data.name); // Model
}

Или оператор ненулевого утверждения:

console.log(this.data!.name); // Model

Обходной путь - обмануть систему набора текста с утверждением:

private data: Model = null as unknown as Model;

Vue-class-component не принимает во внимание TypeScript, потому что undefined легче обрабатывать в TypeScript чем null, особенно потому, что это позволит пометить свойство как необязательное.

Я знаю, что данные никогда не будут нулевыми.

Это будет null, пока компонент не смонтирован, это оставляет место для ошибки:

public created() {
    console.log(this.data.name); // runtime error but no compilation error
}

public mounted() {
    this.data = {...this.$store.getters.data};
}
4
Estus Flask 26 Июн 2019 в 06:25

Вы можете использовать метод получения вместо непосредственного назначения данных, предполагая, что данные устанавливаются в хранилище при его создании. Удостоверьтесь, что ваши покупатели магазина безопасны!

@Component
export default class ClubVue extends Vue {
    private _data: Model | undefined;

    get data(): Model {
        if (!this._data) {
            this._data = {...this.$store.getters.data};
        }
        return this._data;
    }
}

Таким образом, data никогда не будет неопределенным, поскольку он либо возвратит _data, либо установит _data для текущего содержимого хранилища, а затем вернет его.
Это может завершиться ошибкой, если _data является примитивом, а не объектом, и оценивается как false (например, (Number) 0 или (String) ""). В этом случае используйте this._data === undefined вместо !this._data.

Вы также можете сократить получатель до

get data():Model {
    return this._data = this._data || {...this.$store.getters.data};
}

Но это менее очевидно, особенно если читатель не знает, что присвоение вернет присвоенное значение / ссылку, и еще хуже для чтения с примитивными типами:

return this._data = 
    this._data === undefined 
        ? {...this.$store.getters.data} 
        : this._data;
1
CGundlach 26 Июн 2019 в 14:49