javascriptvue.jsvueify

Using Vueify for components with the runtime-only build in Vue.js


I've been working on porting a vue.js component from vue 1.0 to Vue 2.0 using Vueify. In the Starter resources it states:

When you use vue-loader or vueify to import *.vue files, their parts are automatically compiled into render functions. It is therefore recommended to use the runtime-only build with *.vue files.

However, this does not appear to be the case. If I have a simple component like:

<template>
    <div>
        {{ msg }}
    </div>
</template>

<script type="text/javascript">
export default {
    props: {
        msg: {
            default: "Child Message"
        }
    }
}
</script>

And in my main.js file I do:

import Vue from 'vue'
import MyComponent from './my-component.vue';

Vue.component('my-component', MyComponent);

new Vue({
    el: '#app',
    render: function(createElement) {
        return createElement(MyComponent)
    }
});

Then compile with Gulp using:

browserify('./main.js')
    .transform(vueify)
    .bundle()
    .pipe(fs.createWriteStream("bundle.js"))

I cannot do anything at all with the component except get it to render. In fact, it will actually render the component as soon as it finds the div with the id "app":

<div id="app">
  <!-- my-component renders even though I didn't ask it to -->
</div>

And any props added to the component are not received, so:

    <div id="app">
      <!-- 
      Message displays as default "Child Message" rather than "Parent Message". The prop wasn't passed
      -->
      <my-component msg="Parent Message"></my-component>
    </div>

Similarly, if I add data to main.js, it's not accessible from the web page:

import Vue from 'vue'
import MyComponent from './my-component.vue';

Vue.component('my-component', MyComponent);

new Vue({
    el: '#app',
    render: function(createElement) {
        return createElement(MyComponent)
    },
    data() {
        return {
            msg: "Parent Message"
        }
    }
});

in HTML:

<div id="app">
  {{ msg }} // This will not print
</div>

And anything inside "#app" doesn't render at all (remember "my-component" is rendered even if I don't add it):

<div id="app">
  <!-- This doesn't render-->
  <strong>A component </strong>
  <my-component></my-component>
</div>

So it looks to me like you can render a component, without any control over it, and you cant do anything further with the view model, so is it really the case that I should be using the runtime-only build as suggested?

In the end I've used the standalone build using aliasify and everything works fine, but I'd really like to know what it is I am missing when using vueify with the runtime build. Surely the behavior I'm describing isn't what is supposed to happen, so I can only assume I have misunderstood something somewhere.


Solution

  • Doing some tests the problem is in your default render function:

    render: function(createElement) {
        return createElement(MyComponent)
    }
    

    It's overriding the main Vue file's render function and creating a base MyComponent inserting it into the body.

    When I removed the render function the prop fired.

    jsFiddle Try that, just uncomment the render function to see what I mean.

    The render function is meant to replace html templating by allowing you to have more control and utilize other template options.