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。
我最近开始在我的 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。