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

TypeError: Cannot read property 'extend' of undefined

Open marszall87 opened this issue 7 years ago • 14 comments

This happens every time to me when component is reloaded:

TypeError: Cannot read property 'extend' of undefined
    at VM93425 main.js:28952
    at Object.reload (VM93425 main.js:28860)
    at VM93425 main.js:43826
    at Object../src/agilecards/components/edit-settings/TemplateScopeSelector.vue (VM93425 main.js:43831)
    at __webpack_require__ (VM93425 main.js:679)
    at hotApply (VM93425 main.js:608)
    at VM93425 main.js:290
    at <anonymous>

Stack trace is not very helpful, but I tracked this exception to line 196:

const newCtor = record.Ctor.super.extend(options)

Looks like super does not exist in Ctor (and Ctor is the Vue constructor function). I'm using Vue 2.5.2.

marszall87 avatar Nov 06 '17 15:11 marszall87

Please provide a reproduction.

yyx990803 avatar Nov 06 '17 15:11 yyx990803

@marszall87 I solved this problem with changing vue's bootstrap, and there seems no problem. my repo

refrence

danni-cool avatar Nov 10 '17 07:11 danni-cool

@DanielChan27 thanks! I'll try that, we're bootstraping Vue the same way.

marszall87 avatar Nov 13 '17 12:11 marszall87

I also have same problem as @marszall87. The solution from @DanielChan27 worked for me

hadrian625 avatar Jun 13 '18 14:06 hadrian625

I also have same problem

ghost avatar Aug 11 '18 07:08 ghost

import App from './app.vue'
import Vue from 'vue'

const app = new Vue(App).$mount('#root')

image This way will break

vv314 avatar Sep 18 '18 09:09 vv314

I'm also seeing this issue, and we mount our application pretty much the same way as in @vv314's example above, with the exception that we use the el property in our app component definition.

RobertWHurst avatar Oct 24 '18 20:10 RobertWHurst

I also had this issue and it seems like we need to explicitly create the root app instead of creating it directly from our root component.

So instead of this:

import App from './app.vue'
import Vue from 'vue'

const app = new Vue(App).$mount('#root')

I'm using this:

import App from './app.vue'
import Vue from 'vue'

const root= new Vue({
    render: createElement => createElement(App)
}).$mount('#root')

Unfortunatelly the proper way of creating the root instance is very unclear in the official documentation.

ggaborx avatar Oct 27 '18 20:10 ggaborx

@ggaborx Passing an el property in the vue opts is an official way of mounting a Vue component if the documentation is to be believed => https://vuejs.org/v2/api/#el

@yyx990803 This definitely seems like a valid bug.

RobertWHurst avatar Nov 06 '18 20:11 RobertWHurst

@RobertWHurst you can use the el prop instead of $mount but you will still get an error if you would like to do it with SFC. The documentation is unclear about how to directly mount a component instead of a new Vue instance. After a couple of try and fail I suspect its impossible. BTW, I'm using $mount because I need further configuration before mount but after I have the root component. The example above is simplified.

ggaborx avatar Nov 07 '18 06:11 ggaborx

@ggaborx Sorry, I'm not clear on what you mean by SFC. I'm also not sure what you mean in regards to mounting a component vs a Vue instance. By component, do you mean the Vue constructor options object returned by the vue loader?

Calling $mount, or passing the el property are functionally identical (with the exception that calling $mount yourself means you can do stuff beforehand as in your case). Passing an el property as part of your vue options causes vue to automatically call $mount internally. This can be seen in vue/init => https://github.com/vuejs/vue/blob/dev/src/core/instance/init.js#L68

Based on my reading of the source code this is an entirely valid use case, and thus it's clear to me this is a bug.

RobertWHurst avatar Nov 08 '18 05:11 RobertWHurst

@RobertWHurst SFC stands for Single File Component. There is no clear explanation in the documentation how to mount an SFC as the root component. You can set it as the parameter for the Vue constructor: new Vue(myApp). But you cannot define the 'el' prop in this way. So we need to manually call $mount. Basically I don't really need different root component than myApp but I have to create one as the documentation says. Moreover I created a general mount function which allows to configure the root instance after it was created with SFC - so this is the second reason why I call $mount instead of using 'el':

function mount(cmp, configure) {
    ...
    const root = new Vue({
        render: createElement => createElement(cmp)
    })
   
    if (configure) {
        configure(root);
    }

    root.$mount('#root');
}

BTW I agree. It seems like a bug.

ggaborx avatar Nov 08 '18 06:11 ggaborx

@ggaborx The value returned from the vue-template-compiler when requiring the vue file (SFC) is just a plain object. It has the same properties as the object you export in your script tag with the addition of a render method created from your template tag. You are meant to pass to it to the vue constructor. It is not a vue component until you do so. By calling new Vue and passing it the object returned from importing/requiring you are creating your root component, not wrapping it. Until you do this it is just a plain object intended to tell Vue how to build your component; it is the options for the vue constructor.

As an aside you can set an el property in your vue file. If you set the value of el to a css selector, $mount will find the first element matching that selector and mount it there. It can also be a dom node if you query for one yourself.

As an additional aside, when you call new Vue({...}) passing just a render function that uses createElement to create your component, you are actually creating two vue components, I wouldn't recommend doing that as it isn't nessisary.

RobertWHurst avatar Nov 09 '18 03:11 RobertWHurst

I was getting this error as well in my TypeScript Vue application created with the Vue CLI:

image

main.ts:

const app = new Vue({
  render: (h) => h(App),
}).$mount('#app');

Adding the Component argument in the import:

import { Vue, Component } from 'vue-property-decorator';

And then putting the @Component before my class decoration:

@Component
export default class SomeClass extends Vue {
  ...
} 

I had to restart the server serve -s dist. Fixed the issue for me.

alucardu avatar Aug 11 '20 12:08 alucardu