Skip to content
Advertisement

In Vue, what parameters does createElement() actually get?

(This is a further question after this one: In Vue, what is the relationship of template, render, VNode?)

Found createElement()‘s source code (from here):

function createElement (
    context,
    tag,
    data,
    children,
    normalizationType,
    alwaysNormalize
) { ... }

Code

main.js: (partly)

import App from './App.vue'

new Vue({
  el: '#app',
  render: h => h(App),
  router
})

App.vue:

<template>
  <div id="content">
    <!--    <img src="./assets/logo.png" alt="">-->
    <router-view></router-view>
  </div>
</template>

<script>
  export default {}
</script>

Questions

  • A. In App.vue, export default {} will return an empty object, is that correct?
  • B. In main.js:
    • B-1. import App from './App.vue', will bind App to the empty object, is that correct?
    • B-2. render: h => h(App), if the answer to previous two questions were yes, then here h (which is alias of vue’s createElement() function) will get a single parameter, for context with value as empty object, is that correct?
    • B-3. But, that doesn’t make much sense, because the template are actually rendered in the browser in my test, it’s not empty.
  • C. So, in the code above, how many parameters are passed to createElement(), and what is the value of each of them?
  • D. Which part did I misunderstand about Vue or ES6 in above description?

Advertisement

Answer

Single-file components, i.e. .vue files, go through special processing by Vue Loader. See:

https://vue-loader.vuejs.org/#what-is-vue-loader

This will interfere in the export/import process so that everything works as expected.

So:

In App.vue, export default {} will return an empty object, is that correct?

It would for a .js file. But for a .vue file it won’t, not once it’s been through Vue Loader.

Try console logging the value of App in main.js to see what actual gets imported. You should see a render function (compiled from your template) as well a few other little supporting pieces.

Update

To answer your follow-up question from the comments.

createElement just creates a VDOM node. It does not create the component instance for that node. Vue further processes the tree of VDOM nodes after they are returned from render and creates any child component instances it needs. It’ll then call render on those components to generate the VDOM nodes that they need and so on until everything is rendered.

I’ve created a small example to try to illustrate this. It consists of a parent with two component children. Notice that the logging for creating and rendering the child components does not happen straight away when calling createElement. Instead it happens after the render function has returned.

const child = {
  render (createElement) {
    console.log('rendering the child')
    return createElement('div', null, ['hello'])
  },
  
  created () {
    console.log('child is created')
  }
}

new Vue({
  el: '#app',
  
  components: {
    child
  },
  
  created () {
    console.log('parent is created')
  },
  
  render (createElement) {
    console.log('rendering the parent')
    
    const children = [
      createElement('child'),
      createElement('child')
    ]
    
    const root = createElement('div', null, children)
    
    console.log('finished calling createElement')
    
    return root
  }
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id="app"></div>
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement