У меня есть несколько компонентов на странице, и я обнаружил, что обновления родительского объекта отражаются в одном из компонентов, но не в другом.
На главной странице PatientEditor.vue
представлены следующие компоненты:
<notes-editor v-model="pt" />
<chart-completion v-model="pt" arrange="horiz" />
и имеет этот скрипт:
module.exports = {
props: ["pt"]
};
Таким образом, объект pt
находится в родительском объекте и передается нескольким компонентам в виде v-model
Компонент ChartCompletion.vue
работает хорошо. В нем есть все.
module.exports = {
props: ["value", "arrange"],
computed: {
completed_notes: function() {
return this.value.notes.filter(function(note) {
return note.signed_at;
}).length;
},
Мой проблемный ребенок, однако, является шаблоном NotesEditor.vue
который содержит следующее:
module.exports = {
props: ["value"],
computed: {
completed_notes: function() {
return this.value.notes.filter(function(note) {
return note.signed_at;
}).length;
}
},
Не уверен, важно ли это, но объект notes
заполняется из вызова ajax в другом компоненте, например:
this.value.notes.splice(0, this.value.notes.length, ...response.body.notes);
this.$emit("input", this.value);
Sooooo, вот проблема.
Когда this.value.notes
обновляется, результаты видны в компоненте ChartCompletion
, но они не видны в компоненте NotesEditor
. Когда я использую отладчик Vue в chrome, я вижу, что объект заметок изменен, но по какой-то причине вычисленное свойство не перезапускается, хотя оно имеет идентичное определение в компоненте ChartCompletion
. Кроме того, у меня есть v-for
в NotesEditor
который тоже не меняется.
Каков наилучший способ отладить это?
EDIT 1 - включая компонент NotesEditor
<template>
<span>
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Status</th>
<th>Audio</th>
<th>Text</th>
</tr>
</thead>
<tbody>
<tr v-for="n in value.notes" :key="n.id">
<th>{{n.created_at}}</th>
<td>{{n.note_status_id}}</td>
<td>
<span v-if="n.audio_length > 0">
<audio controls="controls" preload="none">
<source :src="audioURL(n.id)" type="audio/webm"> Your browser does not support the audio element.
</audio>
({{n.audio_length}}s)
</span>
<span v-else>
None
</span>
</td>
<td>
<span v-if="n.note_text">
<button data-toggle="tooltip" :title="n.note_text" class="btn btn-outline-primary btn-sm" @click.prevent="openChartEditor(n.id)">
<span class="glyphicon glyphicon-edit"></span> Edit Note ({{ n.note_text.length }} chars)
</button>
</span>
<span v-else>
<button class="btn btn-primary btn-sm" @click.prevent="openChartEditor(n.id)">
<span class="glyphicon glyphicon-pencil"></span> Create Note
</button>
</span>
</td>
</tr>
<tr>
<td colspan="3">
<record v-model="value" />
</td>
<td>
<button class="btn btn-primary" @click.prevent="openChartEditor(0)">
<span class="glyphicon glyphicon-pencil"></span> Create Note
</button>
</td>
</tr>
</tbody>
</table>
</span>
</template>
<script>
module.exports = {
props: ["value"],
data: function() {
return {
sendFaxWorking: false
};
},
computed: {
completed_notes: function() {
return this.value.notes.filter(function(note) {
return note.signed_at;
}).length;
}
},
methods: {
audioURL: function(id) {
return "/notes/getAudio/" + id;
},
openChartEditor: function(id) {
this.$root.$emit("showEditor", id);
}
}
};
</script>
<style>
audio {
vertical-align: middle;
border: 0;
margin: 0;
}
</style>
Я не думаю, что это хороший ответ, но он работает. Я добавил функцию наблюдателя, которая вызывает $forceUpdate()
mounted: function() {
this.$watch("value.notes", this.$forceUpdate);
},
v-for
использует:key=
? такжеthis.value.notes.splice(
мутирует реквизит, вместо этого создайте новый, который вы затем$emit