ค้นหาเว็บไซต์

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
    }
}

บทความที่เกี่ยวข้อง