Are `h` and `createVNode` the same?

2.2k views Asked by At

Both h and createVNode are exposed from vue.

The doc seems to suggest they are the same:

The h() function is a utility to create VNodes. It could perhaps more accurately be named createVNode().

But switch h to createVNode will throw:

<script lang="ts">
  import { createVNode, defineComponent, h } from 'vue'

  export default defineComponent({
    setup() {
      // works
      return () => h('strong', 'Foo')

      // throws
      return () => createVNode('strong', 'Foo')
    },
  })
</script>
3

There are 3 answers

0
Wenfang Du On BEST ANSWER

For h:

props can be omitted when there are no props

You can just do:

h('strong', 'Foo')

For createVNode, you have to do:

createVNode('strong', null, 'Foo')
0
RonaldT On

createVNode is exposed but h is the user friendly variant of it. If you want to call createVNode directly you should add different type of arguments, see:

https://github.com/vuejs/vue-next/blob/060c5f1d0ae999cd8c8fb965e8526ffab17ac2d1/packages/runtime-core/src/vnode.ts#L326


    export const createVNode = (__DEV__
      ? createVNodeWithArgsTransform
      : _createVNode) as typeof _createVNode

    function _createVNode(
      type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,
      props: (Data & VNodeProps) | null = null,
      children: unknown = null,
      patchFlag: number = 0,
      dynamicProps: string[] | null = null,
      isBlockNode = false
    )

1
trokix On
//h method Actual implementation
function h(type, propsOrChildren, children) {
    const l = arguments.length;
    if (l === 2) {
        if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {
            // single vnode without props
            if (isVNode(propsOrChildren)) {
                return createVNode(type, null, [propsOrChildren]);
            }
            // props without children
            return createVNode(type, propsOrChildren);
        }
        else {
            // omit props
            return createVNode(type, null, propsOrChildren);
        }
    }
    else {
        if (l > 3) {
            children = Array.prototype.slice.call(arguments, 2);
        }
        else if (l === 3 && isVNode(children)) {
            children = [children];
        }
        return createVNode(type, propsOrChildren, children);
    }
}