Cade Embery
Cade Embery

Reputation: 450

Programmatically created Vue component missing global properties defined on Vue.prototype

I have an issue when creating an instance of a vue component imported from a bundled rollup library, I add a global property to the root Vue instance using Vue.prototype and it is shared across all of my components, However when i create a new instance using the Vue.extend method, the newly created component has none of the prototype properties or globals they all simply return undefined.



//Main.js
Vue.prototype.$example = 'Hello there!';

//////////////////////////////

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


//App.vue
import { MyDynamicComponent } from 'my-bundled-rollup-library';
export default {
    created() {

        var DynamicComponent = Vue.extend(MyDynamicComponent);

        console.log(this.$example) //Returns 'Hello there!' (correct)
        var instance = new DynamicComponent({
            propsData: {
                hello:'world',
            },
        })

        ///////////////////////////////////////////

        console.log(instance.$example) //Returns undefined (does not have the property)
    }
}

And here is an example of the component before it's bundled

//MyDynamicComponent.vue
const MyDynamicComponent = {
     props:{
          hello:{
               type:String
          }
     },
     created() {
          console.log(this.$example) //undefined
     }
}

export default component
export { MyDynamicComponent as MyDynamicComponent }

My first thought is that somehow the component is using a different Vue instance than the one of Vue.extend

Upvotes: 0

Views: 1862

Answers (2)

Cade Embery
Cade Embery

Reputation: 450

After rm -rf node_modules and reinstalling and trying to recompile my library with rollup again, roll up threw an error that it was not throwing before over an alias to use the Vue runtime+compiler package.

[!] Error: Cannot find module 'vue/dist/vue.esm.js'

My rollup.config file had


import vue from 'rollup-plugin-vue';

import alias from '@rollup/plugin-alias';

export default {
    plugins: {
        alias({
            entries: [
                //Removing this line fixed the problem
                //{ find: 'vue', replacement: require.resolve('vue/dist/vue.esm.js') },
            ],
        }),
        vue,
    }
}

So the lesson learned is, when things are being strange, rm -rf node_modules and rebuild everything again.

Upvotes: 1

Philip
Philip

Reputation: 3536

I've recreated the whole app and it works for me. I transpiled the component with rollup and imported it inside an app generated with the vue CLI.

The only thing that puzzles me is why you didn't import the component as default?

import { MyDynamicComponent } from 'my-bundled-rollup-library';
// to
import MyDynamicComponent from 'my-bundled-rollup-library';

You export it as default, so you have to import it as default.

Info This is the part inside vue which creates the new "sub" prototype object with the "super" prototype https://github.com/vuejs/vue/blob/dev/src/core/global-api/extend.js#L36

rollup.config.js

import vue from 'rollup-plugin-vue'

export default {
  input: 'component.vue',
  output: {
    format: 'esm',
    file: 'dist/MyComponent.js'
  },
  plugins: [
    vue()
  ]
}

dist/MyComponent.js

This is the generated file from MyComponent.vue

import { openBlock, createBlock } from 'vue';

//
//
//

var script = {
  props: {
    hello: {
      type: String,
    },
  },
  created() {
    console.warn('MY_COMPONENT', this.$example); // should work
  },
};

function render(_ctx, _cache) {
  return (openBlock(), createBlock("div", null, "hoi"))
}

script.render = render;
script.__file = "component.vue";

export default script;

App.vue (script tag)

import Vue from 'vue';
import MyComponent from './dist/MyComponent'; // throws some warnings, but this is not relevant for this post

export default {
  name: 'App',
  created() {
    const DynamicComponent = Vue.extend(MyComponent);

    const instance = new DynamicComponent({
      propsData: {
        hello: 'world',
      },
    });

    console.log('instance', instance.$example);
  },
};

Upvotes: 1

Related Questions