vuejs / vue-hot-reload-api

🌶️ Hot reload API for Vue components
MIT License
466 stars 51 forks source link

Component extends another component lost its extended methods after hot reload #68

Open hjkcai opened 6 years ago

hjkcai commented 6 years ago

Description

Component A is defined in a .vue file, and component B is defined in a .js file that extends A. After changing the <script> section of A, B is reloaded but it lost what is extended (for the example below, test() will be gone).

import Vue from 'vue'
import component from './component'

export default Vue.extend({
  extends: component,
  methods: {
    test () {           // test will be lost!
      alert('test!')
    }
  }
})

What is expected

Component B is correctly reloaded.

Reproduction repo

https://github.com/hjkcai/vue-hot-reload-api-issue

Reproduction steps

Edit changeThis() method or any part of the <script> section in component.vue. The console will show the error after hot reload.

What I have found

I tried to step into vue-hot-reload-api to find out this question. It seems that component A and B share the same entry in the map object, which means they have the same data ID (data-v-xxxxxx). After hot reload, the constructor of B is recreated with the options of A. Maybe that is why component B is reloaded without its own methods?

mikerockett commented 6 years ago

Hi all – has anyone had a chance to look into this yet?

scq commented 5 years ago

It looks like this is happening because the hook inserted in makeOptionsHot() is not recording the right record.Ctor value for the parent component.

https://github.com/vuejs/vue-hot-reload-api/blob/5dc0e49332802fa0154de3fed7dde31437309698/src/index.js#L86-L92

If you have component B that extends from component A, this records the wrong record.Ctor value for component A as this.constructor will be pointing to component B's constructor.

I implemented a hacky fix for this by replacing that line with

record.Ctor = options._Ctor ? options._Ctor[0] : undefined;

However this doesn't fully fix the issue as after doing that the component is losing data inherited from the parent component. Possibly the same issue as #67 - I didn't have time to look into this further.

silverprize commented 5 years ago

@scq Thank you!! I've fixed some problem in your code. record.Ctor is not Array that is Object. Works fine below code. Thanks again.

        var ctor
        if (options._Ctor) {
          var key = Object.keys(options._Ctor)[0]
          if (key) {
            ctor = options._Ctor[key]
          }
        }
        if (!ctor) {
          ctor = this.constructor
        }
        record.Ctor = ctor
mikerockett commented 4 years ago

I tried the suggestion(s) above a little while ago, to no avail. Not sure how else to fix the issue with the limited knowledge I have in regards to how the cogs work internally.

Pinging @yyx990803 – I know your focus is currently on a bunch of other things, and I also know that not many others are bringing this issue up, but is there any chance you could take a look at it? Thanks!

nemoDreamer commented 2 years ago

Any movement on this? It's stopping us from using extends altogether, because it makes the Storybook dev workflow so broken.