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

Posted

技术标签:

【中文标题】vue-class-component:如何创建和初始化反射数据【英文标题】:vue-class-component : how to create and initialize reflective data 【发布时间】:2019-09-06 23:08:56 【问题描述】:

我正在使用带有 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;

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

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

这里有合适的初始化数据的方法吗?

【问题讨论】:

【参考方案1】:

此类属性的正确类型是:

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 is easier to handle in TypeScript than null,特别是因为这将允许将属性标记为可选。

我知道数据永远不会为空。

在组件被挂载之前,它将是null,这留下了出错的空间:

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


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

【讨论】:

【参考方案2】:

您可以使用 getter 而不是直接分配数据,假设数据在创建时已在 store 中设置。确保你的 store 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(例如(数字)0 或(字符串)"")。在这种情况下,请使用 this._data === undefined 而不是 !this._data

你也可以将 getter 缩短为

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

但这不太清楚,特别是如果读者不知道赋值将返回被赋值的值/引用,甚至更糟糕的是使用原始类型读取:

return this._data = 
    this._data === undefined 
        ? ...this.$store.getters.data 
        : this._data;

【讨论】:

我支持这种方法,但typeof(this._data) === 'undefined' 是多余的,this._data === undefined 更具可读性但也不必要,因为它可以是未定义的,也可以是这个 sn-p 中的对象。至于private _data: Model | undefined,可以简写为private _data?: Model 是的,在这个 sn-p 中 typeof 是不必要的,我提到它是为了确保读者在适应其他代码时知道原始类型。我同意缩短未定义检查,并将编辑帖子以适应它。虽然我会在我写的时候留下_data 声明,主要是因为它更清楚地表明它最初是undefined。虽然我通常在代码中使用可选参数,但我更喜欢更长、更明确的形式,在这个平台上编写代码时更容易掌握——让初学者更容易理解。谢谢!

以上是关于vue-class-component:如何创建和初始化反射数据的主要内容,如果未能解决你的问题,请参考以下文章

vue-class-component + typescript:如何在导入的函数中使用组件的类作为“this”的类型?

如何在 vue-class-component 中使用动态组件

如何通过 vue-class-component 使用 Vue Router 延迟加载?

vue-class-component 语法中 vue-models(因此,“props”)的计算 getter/setter

具有 vue-class-components 和 typescript 的 vuejs 实例属性时出错

vue-class-component : 调用类方法时 TS2339