vue-hot-reload-api icon indicating copy to clipboard operation
vue-hot-reload-api copied to clipboard

VueRouter beforeRouteEnter hook data changes are not reloaded

Open stoically opened this issue 7 years ago • 7 comments
trafficstars

Hi,

thanks for your work on hot reload!

I'm using vue-hot-reload-api implicitly with webpack dev server and vue-loader. When introducing vue-router into the mix and declaring a beforeRequestEnter hook, hot reloading does not work.

Expected behaviour

Hot reloading should reload data set by vue-routers beforeRequestEnter hook as well.

Actual behaviour

The beforeRequestEnter hook is executed, but the data set on the instance is not reloaded.

Steps to reproduce

Clone https://github.com/stoically/vue-router-hot-reload-issue (based on vue init webpack-simple) npm install npm run dev Navigate to http://localhost:8080 You'll see Message from VueRouter: beforeRouteEnter Now make a change in the src/Router.vue file Message changes to Message from VueRouter: data

Notes

I'm actually not sure if this is expected behaviour. But if it is I would appreciate any pointers on how to achieve hot reloading in this case manually.

Best regards

stoically avatar Dec 16 '17 04:12 stoically

I have been running into this issue this week while looking at moving our product to using beforeRouteEnter guards to preload data. Seems this becomes a non-starter from a development experience though if every time we change the file I have to do a full reload and lose my HMR because the fetched data vanishes?

Any updates or guidance would be appreciated.

wadetandy avatar Aug 17 '18 14:08 wadetandy

I'm also having this issue where all my routes fetch data in the beforeRouteEnter hook as prescribed in the router docs , however this hook is not fired by hot-reload and all data are removed from the component, forcing me to do a full manual reload of the page.

Will the router hooks be supported by hot-reload or are we left with cmd+r for the unforeseeable future?

jorngeorg avatar Oct 22 '18 09:10 jorngeorg

me too

zenghj avatar May 31 '19 03:05 zenghj

yeah having the same issue, my workaround atm is while developing set the data in the mounted hook.

SeoFood avatar Sep 04 '19 16:09 SeoFood

Be cool to get attention on this issue. Guess i have to forgo HMR for now.

boycce avatar Sep 30 '19 19:09 boycce

It has been a while and it seems this still is an issue. Any updates on this?

jacob418 avatar Mar 31 '21 08:03 jacob418

Workaround for Vue2

It will be useful in 95%+ cases when editing a component. In other cases, you will need to reload the page.

// unique for component
let hmrName = 'some-string';

export default {
  created() {
    if (window[hmrName]) {
      Object.assign(this._data, window[hmrName]._data);
    }
  },
  mounted() {
    window[hmrName] = this;
  },
  destroyed() {
    delete window[hmrName];
  },
}

As a mixin with parameters

// src/mixins/hmr.js
export function vHmrStateMixin(name) {
  // NOTE: use only in DEV
  if (!process.env.DEV) {
    return {};
  }

  let store = window._devHmr = window._devHmr || Object.create(null);

  return {
    created() {
      if (store[name]) {
        Object.assign(this._data, store[name]._data);
      }
    },
    mounted() {
      store[name] = this;
    },
    destroyed() {
      delete store[name];
    },
  };
}
// src/views/Home.vue
export { vHmrStateMixin } from '@/mixins/hmr';

export default {
  mixins: [vHmrStateMixin('home')],
  beforeRouteEnter(to, from, next) { ... },
}

Explanation

HMR executes hooks:

NEW.beforeCreate
NEW.created
NEW.beforeMount
OLD.beforeDestroy
OLD.destroyed
NEW.mounted

The order of events is important. We restore the data (_data) as early as possible, in the created hook, when the data has already been initialized. The beforeCreated hook doesn't work for us.

Saving in the mounted hook, and cleaning up in the destroyed hook. These are the only places where we can do it. When the component is destroyed (for example, when changing the page), the destroyed hook will be called, which will remove the reference to the last instance of the component from window. There will be NO memory leaks =)

We use window because we need global storage, but <script> inside * .vue files has local scope.

igisev avatar Sep 15 '21 19:09 igisev