Vue 变量在扩展 TypeScript 父项的子项中没有反应 class

Vue variables not reactive in children of extended TypeScript parent class

我最近开始在我的 Vue.js 项目中使用 TypeScript。对于我当前的项目(一个非常简单的聊天应用程序),我创建了一个名为 ChatParent.ts 的 TypeScript class。它包含 sending/receiving 消息所需的所有方法和变量。我在我的其他组件中扩展了这个 class。从这些子 class 调用父方法工作正常,但是,当我监视父 class 中的变量(例如 username)时,更改未反映在 DOM 的子组件。

我尝试添加 setter/getter 方法和计算属性(例如,get methodName(): boolean),但都不起作用。

下面的代码来自 ChatParent.ts 并且已经过简化。

@Component({
    name: "ChatParent",
})
 export default class ChatParent extends Vue {
    private chatClient: new ChatClient(...);
    subscribed: boolean = false;

    username: string = "";

    subscribe() {
        const subscriptionRequest = new SubscriptionRequest();
        subscriptionRequest.setUsername(username);

        this.chatClient.subscribe(subscriptionRequest).on("data", data => {
            this.subscribed = true;
        });
    }
    ...
}

以下内容来自TypeBox.vue.

<template>
    <v-container pa-2>
        <v-textarea
                outline
                label="Type message here..."
                :disabled="!subscribed"
                v-model="message"
        ></v-textarea>
    </v-container>

</template>

<script lang="ts">
    import {Component} from "vue-property-decorator";
    import ChatParent from "@/components/ChatParent.ts";

    @Component({
        name: "TypeBox",
    })
    export default class TypeBox extends ChatParent {
        message : string = "";
    }
</script>

只要在 subscribe(...) 方法中调用 data 回调,订阅变量就会在父 class 中更新,但更改不会反映在子组件中(其中如果 subscribe 变量为真,它应该启用文本区域。

我认为我对 Vue + TypeScript 的理解可能完全不正确(关于扩展 classes)。因此,我非常感谢您提供一些见解。

我的猜测是您的 类 之一的一些数据可能未定义。在这种情况下,您的数据将不会是反应性的(请参阅:https://github.com/vuejs/vue-class-component#undefined-will-not-be-reactive)。您可以尝试使用此语法,例如 username: string = null!

看来我没有正确理解 Vue/TypeScript 中扩展 classes 的用法。变量数据不在扩展父 class (ChatParent) 的所有 class 之间共享,这就是变量没有触发 DOM 更改的原因。

我使用 Vuex 解决了这个问题,如下:

  class ChatModule extends VuexModule {
  // Variables
  chatClient!: ChatClient;
  subscribed: boolean = false;
  username: string = "";
  messages: string = "";

  // Getters
  get getUsername(): string {
    return this.username;
  }

  get getMessages(): string {
    return this.messages;
  }

  get isSubscribed(): boolean {
    return this.subscribed;
  }

  // Mutations and Actions 
  ...

  export default getModule(ChatModule);
}

Vuex 存储包含所有变量。 TypeBox.vue 组件现在简单地扩展 Vue 并调用存储 actions/getters:

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import chat from "@/store/modules/chat";
@Component({
  name: "TypeBox"
})
export default class TypeBox extends Vue {
  private message: string = "";
  clearMessage(): void {
    this.message = "";
  }
  sendMessage(message: string): void {
    chat.sendMessage(message);
  }
  get isSubscribed(): boolean {
    return chat.isSubscribed;
  }
}
</script>

Vuex 存储 actions/getters/mutations 可以通过使用 vuex-module-decorators npm 模块进行类型安全。

更多详情,see my GitHub repository