阿里云主机折上折
  • 微信号
Current Site:Index > Changes in the render function API

Changes in the render function API

Author:Chuan Chen 阅读数:39797人阅读 分类: Vue.js

Changes in the Render Function API

The render function API in Vue.js has undergone multiple adjustments during version iterations, from createElement to the shorthand h function, and further to the integration with the setup context in the Composition API. These changes directly impact how developers write rendering logic.

Basics of Render Functions in Vue 2.x

In Vue 2.x, render functions are defined via the render option, receiving createElement as the first parameter:

export default {
  render(createElement) {
    return createElement('div', {
      attrs: {
        id: 'container'
      }
    }, [
      createElement('span', 'Hello World')
    ])
  }
}

The parameter structure consists of three parts:

  1. HTML tag name or component options object
  2. Data object (containing props, attrs, domProps, etc.)
  3. Array of child nodes or text content

Shorthand h Function in Vue 3.x

Vue 3.x introduced the more concise h function alias and adjusted the parameter structure:

import { h } from 'vue'

export default {
  render() {
    return h('div', { 
      id: 'container' 
    }, [
      h('span', null, 'Hello World')
    ])
  }
}

Key changes include:

  • Attributes are now flattened and no longer nested under attrs or domProps
  • class and style handling aligns with template syntax
  • The .native modifier is removed; all events are bound via the on prefix

Render Functions in the Composition API

When using render functions in setup(), h can be directly destructured from the context parameter:

import { defineComponent } from 'vue'

export default defineComponent({
  setup(props, { h }) {
    return () => h('div', [
      h('button', { 
        onClick: () => console.log('Clicked') 
      }, 'Submit')
    ])
  }
})

Or more commonly via module import:

import { h } from 'vue'

export default {
  setup() {
    const count = ref(0)
    return () => h('div', [
      h('p', `Count: ${count.value}`),
      h('button', {
        onClick: () => count.value++
      }, 'Increment')
    ])
  }
}

Major Changes in VNode Props Structure

Vue 3 comprehensively refactored the VNode props structure:

// Vue 2.x style
h('div', {
  attrs: { id: 'box' },
  domProps: { innerHTML: '' },
  on: { click: handler }
})

// Vue 3.x style
h('div', {
  id: 'box',
  innerHTML: '',
  onClick: handler
})

Specific changes include:

  • Removal of attrs and domProps namespaces; all DOM attributes are now flat
  • Event listeners uniformly use the onXxx format
  • class and style support the same array/object syntax as templates

Changes in Functional Components

The definition of functional components has completely changed in Vue 3:

// Vue 2.x functional component
export default {
  functional: true,
  render(h, { props }) {
    return h('div', `Message: ${props.text}`)
  }
}

// Vue 3.x functional component
import { h } from 'vue'

function FunctionalComp(props, { slots }) {
  return h('div', slots.default?.())
}

FunctionalComp.props = ['text']

Key differences:

  • The functional: true option is no longer needed
  • Receives props and context as parameters
  • context contains properties like slots, attrs, and emit

Evolution of Slot Handling

The way slots are handled in render functions has also changed significantly:

// Vue 2.x slots
h('Layout', {
  scopedSlots: {
    default: props => h('span', props.text)
  }
})

// Vue 3.x slots
h(Layout, {}, {
  default: props => h('span', props.text)
})

Improvements in Vue 3:

  • Scoped slots are now passed as an object in the third parameter
  • Regular slots and scoped slots are handled uniformly
  • this.$slots in render functions becomes context.slots

Fragment and Portal Support

Vue 3 added native support for multi-root nodes and Portals:

// Fragment example
h('div', [
  h('header', 'Header'),
  h('main', 'Main content'),
  h('footer', 'Footer')
])

// Portal example
import { h, Teleport } from 'vue'

h(Teleport, { to: '#modals' }, [
  h('div', 'This will render in #modals')
])

Adjustments to Custom Directives

The usage of custom directives in render functions has changed:

// Vue 2.x
h('div', {
  directives: [
    { name: 'focus', value: true }
  ]
})

// Vue 3.x
h('div', {
  vFocus: true
})

Main changes:

  • Directives are now passed as properties prefixed with v
  • Directive lifecycle hook names align with components
  • The inserted hook is removed and replaced with mounted

Improvements in Type Support

Vue 3's render function API has been fully optimized for TypeScript:

import { defineComponent, VNode } from 'vue'

interface Props {
  title: string
}

export default defineComponent({
  setup(props: Props): () => VNode {
    return () => h('div', props.title)
  }
})

The type system can now:

  • Infer h function parameter types
  • Validate VNode properties
  • Provide complete context type hints

Performance-Related Changes

The render function implementation includes multiple performance optimizations:

  1. VNode objects are lighter, with unnecessary properties removed
  2. Static node hoisting is completed at compile time
  3. Event caching mechanisms reduce unnecessary updates
// Compiled static nodes are hoisted
const _hoisted = h('div', { class: 'static' })

function render() {
  return h('div', [
    _hoisted,
    h('p', dynamicContent)
  ])
}

Relationship with Template Compilation Output

Understanding template compilation results helps in grasping render functions:

<!-- Template -->
<div :id="containerId">
  <slot name="header" />
</div>

<!-- Compiled render function -->
function render(_ctx, _cache) {
  return h('div', { id: _ctx.containerId }, [
    _ctx.$slots.header?.()
  ])
}

The template compiler now generates code closer to handwritten render functions, further narrowing the differences between the two.

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.