vuejs / core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
47.3k stars 8.28k forks source link

onActivated not triggered in child component with lazy mount #10806

Open DragonnZhang opened 5 months ago

DragonnZhang commented 5 months ago

Vue version

3.4.25

Link to minimal reproduction

https://play.vuejs.org/#eNqFU02P0zAQ/SuWL22lkggKlyWtVNAeAAlWwNESipJJ6sWxLdvxVory3xnHm6zZj+4t43lv9N6byUCPWme+B3pFC1sZrh2x4Hp9YJJ3WhlHPqtOvyWNUR1ZZflUBcLqI5NFHikIxsJBp0XpACtCim8A+ii4jyU+xDl57OZpu8gTKt1SZyslG95mt1ZJFDYECqMVDuACzA/tuJKW0SsydUKvFELdfZ3enOlhO79XJ6j+PvN+a8/hjdEbAxaMB0aXnitNCy62r399hzN+L81O1b1A9IXmT7BK9EFjhH3qZY2yE9yk9ssUL5ftb3t9diDtbCoIDchxwjOKYYfsXrL+IHeX7SYekyOmGDiXNzsQA82WKHmsHPcYf03G+0WHBYel4iKsIw5tkn1Ar1flgpUKO4a3LRioV5sAT0at1xuyP0SZgZ/5UvSAU5IJD2yUjAMu3VPN/WEYopRxLPJQPz2d5Txfcf3IaHLq/136fOhzEPak7u6DaEphYTJ9gwRuIcNLUsLDepO5E8jUf6At/uN6X7M7V8S/4c2e0TCC0fRfWn6lhPg4jj8eTLgrTGOXvc/efaDjP3GgVMA=

Steps to reproduce

Please see reproduction link.

What is expected?

The text should be 'activated triggered'

What is actually happening?

The text is 'activated not triggered'

System Info

No response

Any additional comments?

No response

skirtles-code commented 5 months ago

Seems similar to #7276, though not exactly the same. It might be the same underlying cause.

That other issue has a PR at #7286, but that seems to be only handling cases involving defineAsyncComponent, so it doesn't fix the issue reported here.

quiteeasy commented 5 months ago

The issue goes deeper than the onActivated lifecycle hook not being triggered in async context. The onActivated is not called on all descendant components mounted after a v-if change. I've prepared a demo that illustrates the behavior.

This raises a question about whether the observed results align with the expected behavior or if there might be an inconsistency or potential issue with the way descendant components are handled in this scenario. If using v-show everything works as expected. Seems to be related to mounting components in different ticks from KeepAlive's tick, seemingly they are not cached in KeepAlive as well.

Edit: As a potential workaround for the issue where onActivated is not called on descendant components after a v-if change, you can consider using v-show instead. This seems to resolve the problem and ensures the expected behavior, as the lifecycle hooks are triggered correctly when components are toggled with v-show.

DragonnZhang commented 5 months ago

The issue goes deeper than the onActivated lifecycle hook not being triggered in async context. The onActivated is not called on all descendant components mounted after a v-if change. I've prepared a demo that illustrates the behavior.

This raises a question about whether the observed results align with the expected behavior or if there might be an inconsistency or potential issue with the way descendant components are handled in this scenario. If using v-show everything works as expected. Seems to be related to mounting components in different ticks from KeepAlive's tick, seemingly they are not cached in KeepAlive as well.

Edit: As a potential workaround for the issue where onActivated is not called on descendant components after a v-if change, you can consider using v-show instead. This seems to resolve the problem and ensures the expected behavior, as the lifecycle hooks are triggered correctly when components are toggled with v-show.

You are right. I will try v-show instead. Thank you.

quiteeasy commented 5 months ago

The Vue documentation states that the onActivated and onDeactivated hooks should work not only for the root component cached by <KeepAlive>, but also for descendant components in the cached tree. However, the issue we're facing is that onActivated is not being called on conditional descendants (those toggled with v-if) of cached components.

This raises a couple of questions:

  1. Should we expect onActivated/onDeactivated to be called on conditional descendants of cached components, as per the documentation? Or should we stick to using regular lifecycle hooks for these cases?
  2. If this behavior is considered an inconsistency or a bug, should we document this particular case or try to fix it?

I'm ready to provide a PR to address this issue, but I'd like to get feedback from the team first on the expected behavior and the best approach moving forward.

DragonnZhang commented 5 months ago

I found an easier method to trigger onActivated. Instead of using v-show, just wrap the component with another <KeepAlive>, like this.

edison1105 commented 2 months ago

Note: This behavior is consistent with vue2.