Skip to content

$route.matched[i].instances loses references to instances when router view components are reused #1338

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lehni opened this issue Apr 14, 2017 · 11 comments

Comments

@lehni
Copy link

lehni commented Apr 14, 2017

Version

2.4.0

Reproduction link

http://jsfiddle.net/lehni/Lb0hz1b0/

Steps to reproduce

Click on any of the two router links in the linked example. In the first view, you will see that a reference to the default view instance is defined.

What is expected?

I expect the instances reference to always point to the mapped router view component instances.

What is actually happening?

After navigating to the second link, the reference is gone, although the view component is reused.


I noticed this because I am using the meta field to attach data to routes that are auto-generated from an admin editor schema description described in JavaScript object literals, out of which the full admin is built automatically. I needed a way to retrieve these meta fields in the associated instances of my router view components, and the only way I found to work was:

  computed: {
    routeRecord() {
      for (let route of this.$route.matched) {
        const instances = route.instances
        for (let name in instances) {
          if (this === instances[name]) {
            return route
          }
        }
      }
      return null
    },

    isLastRoute() {
      // Returns true when this router component is the last one in the route.
      const matched = this.$route.matched
      return this.routeRecord === matched[matched.length - 1]
    },

    meta() {
      const record = this.routeRecord
      return record ? record.meta : null
    }
  }

But the route record object loosing the references to the instances breaks this.

It would be nice to have a $meta and $routeRecord property available that link the router view component instances to the associated route record and attached meta data.

Another scenario where I needed this is the isLastRoute property that you can see above, to know if my template needs to provide another router-view or wether it can render its own content, facilitating automatic nesting based on the schema.

@lehni lehni changed the title $route.matched[i].instances looses reference to instances when router view components are reused $route.matched[i].instances loses references to instances when router view components are reused Apr 14, 2017
@ernestoalejo
Copy link

This is also happening with webpack hot module replacement. After the first change this.$route.matched[0].instances only has {default: undefined}.

@ernestoalejo
Copy link

And this is the exact commit where it stops working: 4e3b377

@lehni
Copy link
Author

lehni commented Apr 14, 2017

@ernestoalejo I should add that I had issues with the scenario describe above with versions prior v2.4.0 as well, e.g. that no instances were available yet in created() hooks. I have to verify this to be sure, but upgrading to v2.4.0 solved some issues for me, while also causing this new one.

@lehni
Copy link
Author

lehni commented Apr 19, 2017

...and related this issue, I was wondering when working with nested components why there isn't a standardised way for a matched component at any level of the hierarchy to know the part of the route that matched it, and the meta object that's attached to it?

$route.meta is always the meta object of the last match, no matter from which component template I am accessing it. There is also no easy way to get to the associated route record.

This is why i wrote the code posted above, and that's where I am hitting this bug because I cannot rely on the instances to be set correctly, apparently...

@yyx990803
Copy link
Member

@lehni regarding your last comment, it is indeed possible (although undocumented) - you can access the depth of a router-view component with this.$vnode.data.routerViewDepth, so the matched route record meta would be:

this.$route.matched[this.$vnode.data.routerViewDepth].meta

@lehni
Copy link
Author

lehni commented Apr 22, 2017

@yyx990803 thanks!

Would you consider exposing this?

e.g.:

computed: {
  $routeRecord() {
    return this.$route.matched[this.$vnode.data.routerViewDepth]
  }, 

  $meta() {
    return this.$routeRecord.meta
  }
}

@apexo
Copy link

apexo commented Mar 16, 2018

This seems to be an issue again since vue v2.5.15 (which adds just a single commit: 8200a35).

@yyx990803
Copy link
Member

@apexo thanks, will look into this.

@mahmost
Copy link

mahmost commented Mar 29, 2018

The reproduction uses v3.0.1 and it is is still producing the issue ..
I can confirm the issue is also happening in v2.8.1
I think this should be reopened

@yyx990803
Copy link
Member

yyx990803 commented Apr 2, 2018

This is already fixed (again) in Vue core, will be out in next patch release.

@apexo
Copy link

apexo commented Apr 3, 2018

for reference: vuejs/vue@de42278

lehni added a commit to ditojs/dito that referenced this issue Jun 7, 2018
lehni added a commit to ditojs/dito that referenced this issue Jun 7, 2018
Dirty but it seems to do the trick!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants