关于typescript:vue-class-component:如何创建和初始化反射数据

vue-class-component : how to create and initialize reflective data

我正在将vuejs与typescript和vue-class-component一起使用。 我正在尝试使用反应性数据创建自定义组件。

这是我的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
   
        <input v-model="data.name" placeholder="Name">
        <input v-model="data.value" placeholder="Value">
   
</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};
    }
}

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

Property or method"data" is not defined on the instance but
referenced during render

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

Property 'data' has no initializer and is not definitely assigned in
the constructor

所以我想这样做:

1
private data: Model = null;

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

Type 'null' is not assignable to type 'Model'.

我不希望将数据类型更改为Model | null,因为我将不得不在所有使用它的地方检查数据是否为空,而且我知道数据永远不会为空。

1
private data!: Model;

也不起作用,因为数据将是未定义的,因此不会是被动的。

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

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


此类属性的正确类型是:

1
private data: Model | null = null;

它可以与类型防护一起使用:

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

或非null断言运算符:

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

一种解决方法是使用断言欺骗输入系统:

1
private data: Model = null as unknown as Model;

vue-class-component不考虑TypeScript,因为undefined在TypeScript中比null更容易处理,尤其是因为这将允许将属性标记为可选。

I know that data will never be null.

在安装组件之前,它将一直是null,这留出了出错的余地:

1
2
3
4
5
6
7
public created() {
    console.log(this.data.name); // runtime error but no compilation error
}

public mounted() {
    this.data = {...this.$store.getters.data};
}

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

1
2
3
4
5
6
7
8
9
10
11
@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

您也可以将吸气剂缩短为

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

但这并不清楚,特别是如果读者不知道分配将返回所分配的值/引用,更糟糕的是使用原始类型进行读取:

1
2
3
4
return this._data =
    this._data === undefined
        ? {...this.$store.getters.data}
        : this._data;