1
votes

I have a mixin which contains beforeCreate lifecycle event.

I would like to import that mixin only into certain components, which are directly loaded through router. I don't want to go into each one of them and manually import the mixin, and I would also want to avoid loading it globally.

I believe that the proper way to do it is in route options, possibly overriding the component method, or by adding mixin option for the route (alongside props, meta...).

I requested this new feature, but I guess I was misunderstood, or I didn't understand the proposed solution.

I tried to create main Vue instance and extend it in my components, but the method only executed from the main component.

Is there any way to make this work?

Example of project code is here

1

1 Answers

3
votes

Perhaps I've misunderstood what you're asking but I'd have thought you could achieve this by extending the component:

import Vue from 'vue'
import Router from 'vue-router'

import MyMixin from './mixins/MyMixin'
import MyList from './components/MyList'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/list',
      name: 'list',

      component: {
        extends: MyList,
        mixins: [MyMixin]
      }
    }
    // ...
  ]
})

So rather than using MyList directly it's being extended and the mixin added in.

Or if you've got a lot of them and want to avoid duplication you could do something like this:

export default new Router({
  routes: [
    {
      path: '/list',
      name: 'list',
      doMagic: true,
      component: MyList
    }
    // ...
  ].map(route => {
    if (route.doMagic) {
      route.component = {
        extends: route.component,
        mixins: [MyMixin]
      }
    }

    return route
  })
})

Here I've used a flag called doMagic to determine which components to modify but if you just wanted to change all of them then you wouldn't need such a flag.

That doesn't take nested routes into account but it could be adapted if required.

Likewise if you're using async components then you'll have to fiddle around with the promises but the core principle should be exactly the same.

Update:

Based on the example code provided, the following seems to work with lazily loaded components:

const routes = [
  // ... routes defined as usual
];

const newRoutes = routes.map(route => {
  const originalComponent = route.component;
  let component = null;

  if (typeof originalComponent === 'object') {
    // Components that aren't lazily loaded
    component = wrap(originalComponent);
  } else {
    // Components that are lazily loaded
    component = async () => {
      const module = await originalComponent();

      return wrap(module.default || module);
    }
  }

  return {
    ...route,
    component
  };

  function wrap (cmp) {
    return {
      extends: cmp,
      mixins: [MyMixin]
    }
  }
});

export default new Router({
  routes: newRoutes
});