typescript - @Watch ไม่ถูกเรียกใช้งาน
ดังนั้นลำดับชั้นของฉันจึงถูกตั้งไว้แบบนี้
ราก
แอป
TimelineItem
- TimelineMetadata
- รายการเวลา
- ข้อมูลเมทาดาต้าเวลา
ที่ไหน
ในไฟล์ app.vue เมื่อ mounted ฉันทำการร้องขอ http บางอย่าง และเมื่อได้รับและประมวลผลข้อมูลแล้ว ฉันจะเติมตัวแปร timeline
<template>
<div id="app">
<div class="loading" v-show="loading">Loading ...</div>
<table class="timeline">
<TimelineItem v-for="event in timeline" :key="event.id" :item="event" :players="players" :match="match"></TimelineItem>
</table>
</div>
</template>
export default class App extends Vue {
...
public timeline: any[] = [];
public mounted() {
...
if (!!this.matchId) {
this._getMatchData();
} else {
console.error('MatchId is not defined. ?matchId=....');
}
}
private _getMatchData() {
axios.get(process.env.VUE_APP_API + 'match-timeline-events?filter=' + JSON.stringify(params))
.then((response) => {
this.loading = false;
this.timeline = [];
this.timeline = response.data;
}
...
}
จากนั้นใน TimelineItem ของฉันฉันมีสิ่งนี้:
<template>
<tr>
<td class="time">
...
<TimelineItemMetadata :item="item" :match="match"></TimelineItemMetadata>
</td>
</tr>
</template>
....
@Component({
components: {
...
},
})
export default class TimelineItem extends Vue {
@Prop() item: any;
@Prop() match: any;
@Prop() players: any;
}
</script>
และจากนั้น ใน TimelineItemMetadata ของฉัน:
<template>
<div>
TEST1
{{item}}
</div>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
@Component({})
export default class TimelineItemMetadata extends Vue {
@Prop() item: any;
@Prop() match: any;
@Watch('match') onMatchChanged() {
console.log('TEST');
}
@Watch('item') onItemChanged() {
console.log('ITEM', this.item);
}
public mounted() {
console.log('timeline metadata item component loaded');
}
}
</script>
รายการและการจับคู่ @Watch ไม่ได้ ถูกกระตุ้น แต่กับ Vue-devtools มันบอกว่ามีข้อมูล... และมันพิมพ์ออกมา... ดังนั้นทำไม @Watch ของฉันถึงไม่ถูกกระตุ้น?
คำตอบ #1
ในตัวอย่างของคุณ ดูเหมือนว่า props match และ item ของ property TimelineItemMetadata จะไม่เปลี่ยนแปลงตลอดเวลา: พวกมันถูกตั้งค่าโดย component App เมื่อมันถูกติดตั้ง.
เมื่อฉันอ่านที่นี่ ดูเหมือนว่าคุณจำเป็นต้องส่งพารามิเตอร์ immediate ให้กับ watcher เพื่อให้มันทำงาน ในครั้งแรกที่ prop เปลี่ยนแปลง.
ฉันคิดว่าคุณควรทำดังนี้:
// note typo is fixed
@Watch('match', {immediate: true}) onMatchChanged() {
console.log('TEST');
}
@Watch('item', {immediate: true})) onItemChanged() {
console.log('ITEM', this.item);
}
คำตอบ #2
ในกรณีที่มีคนอื่นพบข้อผิดพลาดเดียวกับฉัน...
ฉันเสียเวลาเป็นชั่วโมงเพราะฉันรีเซ็ตสถานะด้วยอินสแตนซ์ใหม่ของออบเจ็กต์สถานะ (ผิด) แทนที่จะเป็นคุณสมบัติของมัน (ถูกต้อง)
ดังนั้น อยา่เขียนทับอ็อบเจ็กต์สถานะของคุณด้วยอ็อบเจ็กต์ใหม่ แต่ให้เปลี่ยนแปลงคุณสมบัติของมัน
export interface ISample {
property1?: string;
property2?: string;
}
export interface SampleState {
current: ISample;
}
function getDefaultState (): SampleState {
return {
current: {
property1: undefined,
property2: undefined
}
}
}
export const state = getDefaultState
export const mutations: MutationTree<SampleState> = {
setValue (state, value: ISample) {
state.current.property1 = value?.property1
state.current.property2 = value?.property1
},
reset (state) { // Correct
state.current.property1 = undefined
state.current.property2 = undefined
},
reset2 (state) { // Wrong! After resetting @Watch stopped working,
state.current = getDefaultState().current
}
}
export const actions: ActionTree<SampleState, {}> = {
setValue ({ commit }, value: ISample) {
commit('setValue', value)
},
reset ({ commit }) {
commit('reset')
}
}
export const getters: GetterTree<SampleState, {}> = {
property1: (store) => {
return store.current.property1
},
property2: (store) => {
return store.current.property2
}
}
