【发布时间】:2019-12-01 20:56:09
【问题描述】:
背景
我正在使用 Typescript 3.5.3 中基于类的组件在 Vue.js 2.6.10 中构建一个包含大量输入的大型表单。 (在下面的代码 sn-ps 中,我已将其转换为 JS,因为我确信 TS 不是问题。)为了不让用户不知所措,表单被分解为多个组件;一次只向用户显示一个。
父组件
<template>
<form>
<Basic :Container.sync="Container"/>
<!-- More custom components -->
<output>{{Container.name}}</output>
</form>
</template>
Container 对象是要收集的所有数据的包装器。您会看到我将整个对象传递给子组件,而不是只传递请求给子组件的属性。这似乎是固执己见,但我有我的理由。
Form 组件归结为:
// Imports left out for brevity
@Component({ components: { Basic, }, })
export default class Form extends Vue {
private Container
async created() {
this.Container = {
name: null
}
setInterval(()=>{console.log(this.Container.name)}, 5000)
// Logs whatever will be entered in the input in the Basic component
}
}
子组件
引用的组件Basic 是一个普通的输入元素:
<template>
<input v-model="Container.name" @input="emitUpdate">
</template>
使用同样简单的组件定义:
// Imports left out for brevity
@Component({})
export default class Basic extends Vue {
@Prop() Container
emitUpdate() {
console.log(this.Container.name) // Logs whatever was entered in the input
this.$emit('update:container', this.Container)
}
}
问题
我期望看到的是要更新的容器,以及第一个 HTML sn-p 中的 <output> 以显示当前名称。然而,即使变量发生了变化,它也不会,正如两个控制台日志所证明的那样,它们都正确地注册了输入值。
似乎 Vue 的响应性无法将更改注册到 Container 对象,因此不会重新渲染任何 HTML。我该如何解决这个问题?
尝试的解决方案
我尝试使用<Basic … :Container.sync="Container" @Container="Container = $event" /> 明确监听更新事件,但无济于事。
考虑到 Vue 可能不会对对象属性的变化做出反应(毕竟,观察对象也需要设置 deep 选项),我还尝试单独传递 Container 的属性,导致以下结果变化:
在表单的 html 中object is used as the argument to v-bind(我尝试过使用和不使用@update:name):
<Basic … v-bind.sync="Container" @update:name="name=$event"/>
在子组件中,我已更改为 getter 和 setter,以避开“Thou shall not change Props”警告:
<input v-model="Name" @input="emitUpdate">`
@Prop() name
get Name() {return this.name }
set Name(newName) {this.$emit('update:name', newName)}
【问题讨论】:
-
我可以使用纯 'JS' 编写解决方案,但不能使用
TS,我应该吗? -
@EvilArthas 是的,请这样做。问题很可能不是源于打字稿。
标签: vue.js vuejs2 vue-component