7

我正在使用带有 typescript 和 vue-class-component 的 vuejs。我正在尝试使用反应数据创建自定义组件。

这是我的代码:

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

在第一个版本中,我遇到了这个错误:

属性或方法“数据”未在实例上定义,但在渲染期间被引用

这很正常,正如 vue-class-component 页面中所说,未定义的数据不会反射。我需要将数据初始化为空。此外,我得到这个打字稿错误:

属性“数据”没有初始值设定项,也没有在构造函数中明确分配

所以我想这样做:

private data: Model = null;

但我得到这个打字稿错误:

“null”类型不能分配给“Model”类型。

我不想将数据类型更改为,Model | null因为我必须检查数据是否在任何我将使用它的地方都为空,而且我知道数据永远不会为空。

private data!: Model;

也不起作用,因为数据将是未定义的,因此不会是反应性的。

我不想关闭打字稿检查,因为它们对代码的其他部分很有用。

这里有初始化数据的正确方法吗?

4

2 回答 2

13

此类属性的正确类型是:

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};
}
于 2019-06-26T06:11:40.677 回答
2

您可以使用 getter 而不是直接分配数据,假设数据是在创建时在存储中设置的。确保您的商店吸气剂是类型安全的!

@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;
于 2019-06-26T09:07:53.433 回答