Vue-router: $route.matched[i].instances loses references to instances when router view components are reused

Created on 14 Apr 2017  路  11Comments  路  Source: vuejs/vue-router

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.

Most helpful comment

@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

All 11 comments

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

@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.

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

@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

@yyx990803 thanks!

Would you consider exposing this?

e.g.:

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

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

This seems to be an issue again since vue v2.5.15 (which adds just a single commit: https://github.com/vuejs/vue-router/commit/8200a35ce2852da7ebcc63db798644c7ceefa76a).

@apexo thanks, will look into this.

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

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Atinux picture Atinux  路  3Comments

saman picture saman  路  3Comments

baijunjie picture baijunjie  路  3Comments

yyx990803 picture yyx990803  路  3Comments

lbineau picture lbineau  路  3Comments