Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: Cannot read property 'extend' of undefined #61

Open
marszall87 opened this issue Nov 6, 2017 · 14 comments
Open

TypeError: Cannot read property 'extend' of undefined #61

marszall87 opened this issue Nov 6, 2017 · 14 comments

Comments

@marszall87
Copy link

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.

@yyx990803
Copy link
Member

Please provide a reproduction.

@danni-cool
Copy link

danni-cool commented Nov 10, 2017

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

refrence

@marszall87
Copy link
Author

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

@hadrian625
Copy link

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

@ghost
Copy link

ghost commented Aug 11, 2018

I also have same problem

@vv314
Copy link

vv314 commented Sep 18, 2018

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

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

image
This way will break

@RobertWHurst
Copy link

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.

@ggaborx
Copy link

ggaborx commented Oct 27, 2018

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.

@RobertWHurst
Copy link

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

@ggaborx
Copy link

ggaborx commented Nov 7, 2018

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

@RobertWHurst
Copy link

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

@ggaborx
Copy link

ggaborx commented Nov 8, 2018

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

@RobertWHurst
Copy link

RobertWHurst commented Nov 9, 2018

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

@alucardu
Copy link

alucardu commented Aug 11, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants