Skip to content

Render Functions & JSX ​

Vue āĻŦ⧇āĻļāĻŋāϰāĻ­āĻžāĻ— āĻ•ā§āώ⧇āĻ¤ā§āϰ⧇ āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύ āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ āĻŸā§‡āĻŽāĻĒā§āϞ⧇āϟ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āĻĒāϰāĻžāĻŽāĻ°ā§āĻļ āĻĻ⧇āϝāĻŧāĨ¤ āϝāĻžāχāĻšā§‹āĻ•, āĻāĻŽāύ āĻĒāϰāĻŋāĻ¸ā§āĻĨāĻŋāϤāĻŋ āϰāϝāĻŧ⧇āϛ⧇ āϝ⧇āĻ–āĻžāύ⧇ āφāĻŽāĻžāĻĻ⧇āϰ āϜāĻžāĻ­āĻžāĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āĻŸā§‡āϰ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽā§āϝāĻžāϟāĻŋāĻ• āĻļāĻ•ā§āϤāĻŋ āĻĒā§āϰāϝāĻŧā§‹āϜāύāĨ¤ āϏ⧇āĻ–āĻžāύ⧇āχ āφāĻŽāϰāĻž āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŋāĨ¤

āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āĻ­āĻžāĻ°ā§āϚ⧁āϝāĻŧāĻžāϞ DOM āĻāĻŦāĻ‚ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āϧāĻžāϰāĻŖāĻžāϝāĻŧ āύāϤ⧁āύ āĻšāύ, āϤāĻžāĻšāϞ⧇ āĻĒā§āϰāĻĨāĻŽā§‡ āϰ⧇āĻ¨ā§āĻĄāĻžāϰāĻŋāĻ‚ āĻŽā§‡āĻ•āĻžāύāĻŋāϜāĻŽ āĻ…āĻ§ā§āϝāĻžāϝāĻŧāϟāĻŋ āĻĒāĻĄāĻŧāϤ⧇ āϭ⧁āϞāĻŦ⧇āύ āύāĻžāĨ¤

Basic Usage ​

Creating Vnodes ​

Vue vnodes āϤ⧈āϰāĻŋ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ h() āĻĢāĻžāĻ‚āĻļāύ āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇:

js
import { h } from 'vue'

const vnode = h(
  'div', // type
  { id: 'foo', class: 'bar' }, // props
  [
    /* children */
  ]
)

h() hyperscript-āĻāϰ āϜāĻ¨ā§āϝ āϏāĻ‚āĻ•ā§āώāĻŋāĻĒā§āϤ - āϝāĻžāϰ āĻŽāĻžāύ⧇ "āϜāĻžāĻ­āĻžāĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āϟ āϝāĻž HTML (āĻšāĻžāχāĻĒāĻžāϰāĻŸā§‡āĻ•ā§āϏāϟ āĻŽāĻžāĻ°ā§āĻ•āφāĻĒ āĻ­āĻžāώāĻž) āϤ⧈āϰāĻŋ āĻ•āϰ⧇"āĨ¤ āĻāχ āύāĻžāĻŽāϟāĻŋ āĻ…āύ⧇āĻ• āĻ­āĻžāĻ°ā§āϚ⧁āϝāĻŧāĻžāϞ DOM āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ āĻĻā§āĻŦāĻžāϰāĻž āĻļ⧇āϝāĻŧāĻžāϰ āĻ•āϰāĻž āĻ•āύāϭ⧇āύāĻļāύ āĻĨ⧇āϕ⧇ āωāĻ¤ā§āϤāϰāĻžāϧāĻŋāĻ•āĻžāϰāϏ⧂āĻ¤ā§āϰ⧇ āĻĒā§āϰāĻžāĻĒā§āϤāĨ¤ āĻāĻ•āϟāĻŋ āφāϰāĻ“ āĻŦāĻ°ā§āĻŖāύāĻžāĻŽā§‚āϞāĻ• āύāĻžāĻŽ āĻšāϤ⧇ āĻĒāĻžāϰ⧇ createVNode(), āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻāĻ•āϟāĻŋ āϛ⧋āϟ āύāĻžāĻŽ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰ⧇ āϝāĻ–āύ āφāĻĒāύāĻžāϕ⧇ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ⧇ āĻ…āύ⧇āĻ•āĻŦāĻžāϰ āĻāχ āĻĢāĻžāĻ‚āĻļāύāϟāĻŋ āĻ•āϞ āĻ•āϰāϤ⧇ āĻšāϝāĻŧāĨ¤

h() āĻĢāĻžāĻ‚āĻļāύāϟāĻŋ āϖ⧁āĻŦ āύāĻŽāύ⧀āϝāĻŧ āĻšāĻ“āϝāĻŧāĻžāϰ āϜāĻ¨ā§āϝ āĻĄāĻŋāϜāĻžāχāύ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇:

js
// all arguments except the type are optional
h('div')
h('div', { id: 'foo' })

// both attributes and properties can be used in props
// Vue automatically picks the right way to assign it
h('div', { class: 'bar', innerHTML: 'hello' })

// props modifiers such as `.prop` and `.attr` can be added
// with `.` and `^` prefixes respectively
h('div', { '.name': 'some-name', '^width': '100' })

// class and style have the same object / array
// value support that they have in templates
h('div', { class: [foo, { bar }], style: { color: 'red' } })

// event listeners should be passed as onXxx
h('div', { onClick: () => {} })

// children can be a string
h('div', { id: 'foo' }, 'hello')

// props can be omitted when there are no props
h('div', 'hello')
h('div', [h('span', 'hello')])

// children array can contain mixed vnodes and strings
h('div', ['hello', h('span', 'hello')])

āĻĢāϞāĻ¸ā§āĻŦāϰ⧂āĻĒ vnode āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āφāĻ•ā§ƒāϤāĻŋ āφāϛ⧇:

js
const vnode = h('div', { id: 'foo' }, [])

vnode.type // 'div'
vnode.props // { id: 'foo' }
vnode.children // []
vnode.key // null

āĻŦāĻŋāσāĻĻā§āϰāσ

āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ VNode āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏ⧇ āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻ…āύ⧇āĻ• āĻ…āĻ­ā§āϝāĻ¨ā§āϤāϰ⧀āĻŖ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āϰāϝāĻŧ⧇āϛ⧇, āϤāĻŦ⧇ āĻāĻ–āĻžāύ⧇ āϤāĻžāϞāĻŋāĻ•āĻžāϭ⧁āĻ•ā§āϤ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝāϗ⧁āϞāĻŋ āĻŦā§āϝāϤ⧀āϤ āĻ…āĻ¨ā§āϝ āϕ⧋āύ⧋ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ⧇āϰ āωāĻĒāϰ āύāĻŋāĻ°ā§āĻ­āϰ āύāĻž āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻāϟāĻŋ āĻĻ⧃āĻĸāĻŧāĻ­āĻžāĻŦ⧇ āϏ⧁āĻĒāĻžāϰāĻŋāĻļ āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤ āĻ…āĻ­ā§āϝāĻ¨ā§āϤāϰ⧀āĻŖ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝāϗ⧁āϞāĻŋ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰāĻž āĻšāϞ⧇ āĻāϟāĻŋ āĻ…āύāĻŋāĻšā§āĻ›āĻžāĻ•ā§ƒāϤ āĻ­āĻžāĻ™ā§āĻ—āύ āĻāĻĄāĻŧāĻžāϝāĻŧāĨ¤

Declaring Render Functions ​

Composition API āĻāϰ āϏāĻžāĻĨ⧇ āĻŸā§‡āĻŽāĻĒā§āϞ⧇āϟ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ, setup() āĻšā§āϕ⧇āϰ āϰāĻŋāϟāĻžāĻ°ā§āύ āĻŽāĻžāύ āĻŸā§‡āĻŽāĻĒā§āϞ⧇āĻŸā§‡ āĻĄā§‡āϟāĻž āĻĒā§āϰāĻ•āĻžāĻļ āĻ•āϰāϤ⧇ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšāϝāĻŧāĨ¤ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ, āϝāĻžāχāĻšā§‹āĻ•, āφāĻŽāϰāĻž āĻāϰ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤ⧇ āϏāϰāĻžāϏāϰāĻŋ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ āĻĢ⧇āϰāϤ āĻĻāĻŋāϤ⧇ āĻĒāĻžāϰāĻŋ:

js
import { ref, h } from 'vue'

export default {
  props: {
    /* ... */
  },
  setup(props) {
    const count = ref(1)

    // return the render function
    return () => h('div', props.msg + count.value)
  }
}

āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύāϟāĻŋ āϏ⧇āϟāφāĻĒ() āĻāϰ āĻ­āĻŋāϤāϰ⧇ āĻ˜ā§‹āώāĻŖāĻž āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇ āϤāĻžāχ āĻāϟāĻŋ āĻ¸ā§āĻŦāĻžāĻ­āĻžāĻŦāĻŋāĻ•āĻ­āĻžāĻŦ⧇āχ āĻĒā§āϰāĻĒāϏ āĻāĻŦāĻ‚ āĻāĻ•āχ āϏ⧁āϝ⧋āϗ⧇ āĻ˜ā§‹āώāĻŋāϤ āϝ⧇āϕ⧋āύ⧋ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻžāĻļā§€āϞ āĻ…āĻŦāĻ¸ā§āĻĨāĻžāϰ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āϰāϝāĻŧ⧇āϛ⧇āĨ¤

āĻāĻ•āϟāĻŋ āĻāĻ•āĻ• āĻ­āύ⧋āĻĄ āĻĢ⧇āϰāϤ āĻĻ⧇āĻ“āϝāĻŧāĻžāϰ āĻĒāĻžāĻļāĻžāĻĒāĻžāĻļāĻŋ, āφāĻĒāύāĻŋ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āĻŦāĻž āĻ…ā§āϝāĻžāϰ⧇āĻ“ āĻĢ⧇āϰāϤ āĻĻāĻŋāϤ⧇ āĻĒāĻžāϰ⧇āύ:

js
export default {
  setup() {
    return () => 'hello world!'
  }
}
js
import { h } from 'vue'

export default {
  setup() {
    // use an array to return multiple root nodes
    return () => [
      h('div'),
      h('div'),
      h('div')
    ]
  }
}

TIP

āϏāϰāĻžāϏāϰāĻŋ āĻŽāĻžāύ āĻĢ⧇āϰāϤ āĻĻ⧇āĻ“āϝāĻŧāĻžāϰ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤ⧇ āĻāĻ•āϟāĻŋ āĻĢāĻžāĻ‚āĻļāύ āĻĢ⧇āϰāϤ āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧁āύ! setup() āĻĢāĻžāĻ‚āĻļāύ āĻĒā§āϰāϤāĻŋ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡ āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āĻāĻ•āĻŦāĻžāϰ āĻ•āϞ āĻ•āϰāĻž āĻšāϝāĻŧ, āϝāĻ–āύ āϰāĻŋāϟāĻžāĻ°ā§āύ āĻ•āϰāĻž āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ āĻāĻ•āĻžāϧāĻŋāĻ•āĻŦāĻžāϰ āĻ•āϞ āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤

āφāĻŽāϰāĻž render āĻŦāĻŋāĻ•āĻ˛ā§āĻĒ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ āĻ˜ā§‹āώāĻŖāĻž āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŋ:

js
import { h } from 'vue'

export default {
  data() {
    return {
      msg: 'hello'
    }
  },
  render() {
    return h('div', this.msg)
  }
}

render() āĻĢāĻžāĻ‚āĻļāύ⧇āϰ this āĻāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āχāύāĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āϏ⧇ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āφāϛ⧇āĨ¤

āĻāĻ•āϟāĻŋ āĻāĻ•āĻ• āĻ­āύ⧋āĻĄ āĻĢ⧇āϰāϤ āĻĻ⧇āĻ“āϝāĻŧāĻžāϰ āĻĒāĻžāĻļāĻžāĻĒāĻžāĻļāĻŋ, āφāĻĒāύāĻŋ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āĻŦāĻž āĻ…ā§āϝāĻžāϰ⧇āĻ“ āĻĢ⧇āϰāϤ āĻĻāĻŋāϤ⧇ āĻĒāĻžāϰ⧇āύ:

js
export default {
  render() {
    return 'hello world!'
  }
}
js
import { h } from 'vue'

export default {
  render() {
    // use an array to return multiple root nodes
    return [
      h('div'),
      h('div'),
      h('div')
    ]
  }
}

āϝāĻĻāĻŋ āĻāĻ•āϟāĻŋ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡āϰ āϕ⧋āύ⧋ āχāύāĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āϏ āĻ¸ā§āĻŸā§‡āĻŸā§‡āϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύ āύāĻž āĻšāϝāĻŧ, āϤāĻŦ⧇ āϏ⧇āϗ⧁āϞāĻŋāϕ⧇ āϏāĻ‚āĻ•ā§āώāĻŋāĻĒā§āϤāϤāĻžāϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ āĻĢāĻžāĻ‚āĻļāύ āĻšāĻŋāϏāĻžāĻŦ⧇ āϏāϰāĻžāϏāϰāĻŋ āĻ˜ā§‹āώāĻŖāĻž āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇:

js
function Hello() {
  return 'hello world!'
}

āĻāϟāĻž āĻ āĻŋāĻ•, āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āĻŦ⧈āϧ Vue āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ! āĻāχ āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āφāϰāĻ“ āĻŦāĻŋāĻ¸ā§āϤāĻžāϰāĻŋāϤ āϜāĻžāύāĻžāϰ āϜāĻ¨ā§āϝ āĻ•āĻžāĻ°ā§āϝāĻŽā§‚āϞāĻ• āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āĻĻ⧇āϖ⧁āύāĨ¤

Vnodes Must Be Unique ​

āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āĻŸā§āϰāĻŋāϰ āϏāĻŽāĻ¸ā§āϤ āĻ­āύ⧋āĻĄ āĻ…āĻŦāĻļā§āϝāχ āĻ…āύāĻ¨ā§āϝ āĻšāϤ⧇ āĻšāĻŦ⧇āĨ¤ āϤāĻžāϰ āĻŽāĻžāύ⧇ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύāϟāĻŋ āĻ…āĻŦ⧈āϧ:

js
function render() {
  const p = h('p', 'hi')
  return h('div', [
    // Yikes - duplicate vnodes!
    p,
    p
  ])
}

āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āϏāĻ¤ā§āϝāĻŋāχ āĻāĻ•āχ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ/ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϕ⧇ āĻ…āύ⧇āĻ•āĻŦāĻžāϰ āύāĻ•āϞ āĻ•āϰāϤ⧇ āϚāĻžāύ āϤāĻŦ⧇ āφāĻĒāύāĻŋ āĻĢā§āϝāĻžāĻ•ā§āϟāϰāĻŋ āĻĢāĻžāĻ‚āĻļāύ āĻĻāĻŋāϝāĻŧ⧇ āϤāĻž āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤ āωāĻĻāĻžāĻšāϰāĻŖāĻ¸ā§āĻŦāϰ⧂āĻĒ, āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύāϟāĻŋ 20āϟāĻŋ āĻ…āĻ­āĻŋāĻ¨ā§āύ āĻ…āύ⧁āĻšā§āϛ⧇āĻĻ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻ•āϰāĻžāϰ āĻāĻ•āϟāĻŋ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻŦ⧈āϧ āωāĻĒāĻžāϝāĻŧ:

js
function render() {
  return h(
    'div',
    Array.from({ length: 20 }).map(() => {
      return h('p', 'hi')
    })
  )
}

JSX / TSX ​

JSX āĻšāϞ āϜāĻžāĻ­āĻžāĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āĻŸā§‡āϰ āĻāĻ•āϟāĻŋ XML-āĻāϰ āĻŽāϤ⧋ āĻāĻ•ā§āϏāĻŸā§‡āύāĻļāύ āϝāĻž āφāĻŽāĻžāĻĻ⧇āϰāϕ⧇ āĻāχāϰāĻ•āĻŽ āϕ⧋āĻĄ āϞāĻŋāĻ–āϤ⧇ āĻĻ⧇āϝāĻŧ:

jsx
const vnode = <div>hello</div>

JSX āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ⧇āϰ āĻ­āĻŋāϤāϰ⧇, āĻ—āϤāĻŋāĻļā§€āϞ āĻŽāĻžāύāϗ⧁āϞāĻŋ āĻāĻŽā§āĻŦ⧇āĻĄ āĻ•āϰāϤ⧇ āϕ⧋āρāĻ•āĻĄāĻŧāĻž āϧāύ⧁āĻ°ā§āĻŦāĻ¨ā§āϧāύ⧀ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ:

jsx
const vnode = <div id={dynamicId}>hello, {userName}</div>

create-vue āĻāĻŦāĻ‚ Vue CLI āωāĻ­āϝāĻŧ⧇āϰāχ āĻĒā§āϰāĻŋ-āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ āĻ•āϰāĻž JSX āϏāĻŽāĻ°ā§āĻĨāύ āϏāĻš āĻ¸ā§āĻ•ā§āϝāĻžāĻĢā§‹āĻ˛ā§āĻĄāĻŋāĻ‚ āĻĒā§āϰāĻ•āĻ˛ā§āĻĒ⧇āϰ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒ āϰāϝāĻŧ⧇āϛ⧇āĨ¤ āφāĻĒāύāĻŋ āϝāĻĻāĻŋ JSX āĻŽā§āϝāĻžāύ⧁āϝāĻŧāĻžāϞāĻŋ āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ āĻ•āϰ⧇āύ, āϤāĻžāĻšāϞ⧇ āĻŦāĻŋāĻ¸ā§āϤāĻžāϰāĻŋāϤ āϜāĻžāύāĻžāϰ āϜāĻ¨ā§āϝ āĻ…āύ⧁āĻ—ā§āϰāĻš āĻ•āϰ⧇ @vue/babel-plugin-jsx āĻāϰ āĻĄāϕ⧁āĻŽā§‡āĻ¨ā§āĻŸā§‡āĻļāύ āĻĻ⧇āϖ⧁āύāĨ¤

āϝāĻĻāĻŋāĻ“ āĻĒā§āϰāĻĨāĻŽ āϰāĻŋāĻ…ā§āϝāĻžāĻ•ā§āϟ āĻĻā§āĻŦāĻžāϰāĻž āĻĒā§āϰāĻŦāĻ°ā§āϤāĻŋāϤ āĻšāϝāĻŧ, JSX āĻāϰ āφāϏāϞ⧇ āϕ⧋āύ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āϰāĻžāύāϟāĻžāχāĻŽ āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŦāĻŋāĻĻā§āϝāĻž āύ⧇āχ āĻāĻŦāĻ‚ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āφāωāϟāĻĒ⧁āĻŸā§‡ āĻ•āĻŽā§āĻĒāĻžāχāϞ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āφāϗ⧇ JSX-āĻāϰ āϏāĻžāĻĨ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇ āĻĨāĻžāϕ⧇āύ, āϤāĻžāĻšāϞ⧇ āĻŽāύ⧇ āϰāĻžāĻ–āĻŦ⧇āύ Vue JSX transform React-āĻāϰ JSX transform āĻĨ⧇āϕ⧇ āφāϞāĻžāĻĻāĻž, āϤāĻžāχ āφāĻĒāύāĻŋ Vue āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύ⧇ React-āĻāϰ JSX āϰ⧂āĻĒāĻžāĻ¨ā§āϤāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŦ⧇āύ āύāĻžāĨ¤ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž JSX āĻĨ⧇āϕ⧇ āĻ•āĻŋāϛ⧁ āωāĻ˛ā§āϞ⧇āĻ–āϝ⧋āĻ—ā§āϝ āĻĒāĻžāĻ°ā§āĻĨāĻ•ā§āϝ āĻ…āĻ¨ā§āϤāĻ°ā§āϭ⧁āĻ•ā§āϤ:

  • āφāĻĒāύāĻŋ āĻĒā§āϰāĻĒ āĻšāĻŋāϏāĻžāĻŦ⧇ HTML āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āϝ⧇āĻŽāύ class āĻāĻŦāĻ‚ for āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ - className āĻŦāĻž htmlFor āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āĻĻāϰāĻ•āĻžāϰ āύ⧇āχāĨ¤
  • āĻŦāĻžāĻšā§āϚāĻžāĻĻ⧇āϰ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡ (āϝ⧇āĻŽāύ āĻ¸ā§āϞāϟ) āĻĒāĻžāϏ āĻ•āϰāĻž works differentlyāĨ¤

Vue āĻāϰ āϟāĻžāχāĻĒ āϏāĻ‚āĻœā§āĻžāĻž āϟāĻŋāĻāϏāĻāĻ•ā§āϏ āĻŦā§āϝāĻŦāĻšāĻžāϰ⧇āϰ āϜāĻ¨ā§āϝ āϟāĻžāχāĻĒ āχāύāĻĢāĻžāϰ⧇āĻ¨ā§āϏāĻ“ āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇āĨ¤ TSX āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ, tsconfig.json-āĻ "jsx": "preserve" āωāĻ˛ā§āϞ⧇āĻ– āĻ•āϰāϤ⧇ āϭ⧁āϞāĻŦ⧇āύ āύāĻž āϝāĻžāϤ⧇ TypeScript Vue JSX āϰ⧂āĻĒāĻžāĻ¨ā§āϤāϰ āĻĒā§āϰāĻ•ā§āϰāĻŋāϝāĻŧāĻžāϰ āϜāĻ¨ā§āϝ JSX āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ āĻ…āĻ•ā§āώāϤ āϰāĻžāϖ⧇āĨ¤

JSX Type Inference ​

āϰ⧂āĻĒāĻžāĻ¨ā§āϤāϰ⧇āϰ āĻ…āύ⧁āϰ⧂āĻĒ, Vue-āĻāϰ JSX-āĻāϰāĻ“ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āϧāϰāύ⧇āϰ āϏāĻ‚āĻœā§āĻžāĻž āĻĒā§āϰāϝāĻŧā§‹āϜāύāĨ¤

Vue 3.4 āĻĨ⧇āϕ⧇ āĻļ⧁āϰ⧁ āĻ•āϰ⧇, Vue āφāϰ āĻĒāϰ⧋āĻ•ā§āώāĻ­āĻžāĻŦ⧇ āĻŦāĻŋāĻļā§āĻŦāĻŦā§āϝāĻžāĻĒā§€ JSX āύāĻžāĻŽāĻ¸ā§āĻĨāĻžāύ āύāĻŋāĻŦāĻ¨ā§āϧāύ āĻ•āϰ⧇ āύāĻžāĨ¤ Vue-āĻāϰ JSX āϟāĻžāχāĻĒ āϏāĻ‚āĻœā§āĻžāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ TypeScript-āϕ⧇ āύāĻŋāĻ°ā§āĻĻ⧇āĻļ āĻĻāĻŋāϤ⧇, āφāĻĒāύāĻžāϰ tsconfig.json-āĻ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤāϗ⧁āϞāĻŋ āĻ…āĻ¨ā§āϤāĻ°ā§āϭ⧁āĻ•ā§āϤ āĻ•āϰāϤ⧇ āϭ⧁āϞāĻŦ⧇āύ āύāĻž:

json
{
  "compilerOptions": {
    "jsx": "preserve",
    "jsxImportSource": "vue"
    // ...
  }
}

āφāĻĒāύāĻŋ āĻĢāĻžāχāϞ⧇āϰ āĻļā§€āĻ°ā§āώ⧇ āĻāĻ•āϟāĻŋ /* @jsxImportSource vue */ āĻŽāĻ¨ā§āϤāĻŦā§āϝ āϝ⧋āĻ— āĻ•āϰ⧇ āĻĢāĻžāχāϞ āĻĒā§āϰāϤāĻŋ āĻ…āĻĒā§āϟ-āχāύ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤

āϝāĻĻāĻŋ āĻāĻŽāύ āϕ⧋āĻĄ āĻĨāĻžāϕ⧇ āϝāĻž āĻ—ā§āϞ⧋āĻŦāĻžāϞ JSX āύāĻžāĻŽāĻ¸ā§āĻĨāĻžāύ⧇āϰ āωāĻĒāĻ¸ā§āĻĨāĻŋāϤāĻŋāϰ āωāĻĒāϰ āύāĻŋāĻ°ā§āĻ­āϰ āĻ•āϰ⧇, āϤāĻžāĻšāϞ⧇ āφāĻĒāύāĻŋ āφāĻĒāύāĻžāϰ āĻĒā§āϰāĻœā§‡āĻ•ā§āĻŸā§‡ āĻ¸ā§āĻĒāĻˇā§āϟāĻ­āĻžāĻŦ⧇ vue/jsx āφāĻŽāĻĻāĻžāύāĻŋ āĻŦāĻž āωāĻ˛ā§āϞ⧇āĻ– āĻ•āϰ⧇ āϏāĻ āĻŋāĻ• āĻĒā§āϰāĻžāĻ•-3.4 āĻŦ⧈āĻļā§āĻŦāĻŋāĻ• āφāϚāϰāĻŖ āĻŦāϜāĻžāϝāĻŧ āϰāĻžāĻ–āϤ⧇ āĻĒāĻžāϰ⧇āύ, āϝāĻž āĻŦāĻŋāĻļā§āĻŦāĻŦā§āϝāĻžāĻĒā§€ JSX āύāĻžāĻŽāĻ¸ā§āĻĨāĻžāύ āύāĻŋāĻŦāĻ¨ā§āϧāύ āĻ•āϰ⧇āĨ¤

Render Function Recipes ​

āύ⧀āĻšā§‡ āφāĻŽāϰāĻž āĻŸā§‡āĻŽāĻĒā§āϞ⧇āϟ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝāϗ⧁āϞāĻŋāϕ⧇ āϤāĻžāĻĻ⧇āϰ āϏāĻŽāϤ⧁āĻ˛ā§āϝ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ / JSX āĻšāĻŋāϏāĻžāĻŦ⧇ āĻĒā§āϰāϝāĻŧā§‹āĻ— āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻ•āĻŋāϛ⧁ āϏāĻžāϧāĻžāϰāĻŖ āϰ⧇āϏāĻŋāĻĒāĻŋ āϏāϰāĻŦāϰāĻžāĻš āĻ•āϰāĻŦāĨ¤

v-if ​

Template:

template
<div>
  <div v-if="ok">yes</div>
  <span v-else>no</span>
</div>

āϏāĻŽāϤ⧁āĻ˛ā§āϝ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ / JSX:

js
h('div', [ok.value ? h('div', 'yes') : h('span', 'no')])
jsx
<div>{ok.value ? <div>yes</div> : <span>no</span>}</div>
js
h('div', [this.ok ? h('div', 'yes') : h('span', 'no')])
jsx
<div>{this.ok ? <div>yes</div> : <span>no</span>}</div>

v-for ​

Template:

template
<ul>
  <li v-for="{ id, text } in items" :key="id">
    {{ text }}
  </li>
</ul>

āϏāĻŽāϤ⧁āĻ˛ā§āϝ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ / JSX:

js
h(
  'ul',
  // assuming `items` is a ref with array value
  items.value.map(({ id, text }) => {
    return h('li', { key: id }, text)
  })
)
jsx
<ul>
  {items.value.map(({ id, text }) => {
    return <li key={id}>{text}</li>
  })}
</ul>
js
h(
  'ul',
  this.items.map(({ id, text }) => {
    return h('li', { key: id }, text)
  })
)
jsx
<ul>
  {this.items.map(({ id, text }) => {
    return <li key={id}>{text}</li>
  })}
</ul>

v-on ​

āĻāĻ•āϟāĻŋ āĻŦāĻĄāĻŧ āĻšāĻžāϤ⧇āϰ āĻ…āĻ•ā§āώāϰ āĻĻā§āĻŦāĻžāϰāĻž on āĻĻāĻŋāϝāĻŧ⧇ āĻļ⧁āϰ⧁ āĻšāĻ“āϝāĻŧāĻž āύāĻžāĻŽāϗ⧁āϞāĻŋāϕ⧇ āχāϭ⧇āĻ¨ā§āϟ āĻļā§āϰ⧋āϤāĻž āĻšāĻŋāϏāĻžāĻŦ⧇ āĻŦāĻŋāĻŦ⧇āϚāύāĻž āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤ āωāĻĻāĻžāĻšāϰāĻŖāĻ¸ā§āĻŦāϰ⧂āĻĒ, āĻŸā§‡āĻŽāĻĒā§āϞ⧇āĻŸā§‡ @click āĻāϰ āϏāĻŽāϤ⧁āĻ˛ā§āϝ onClickāĨ¤

js
h(
  'button',
  {
    onClick(event) {
      /* ... */
    }
  },
  'Click Me'
)
jsx
<button
  onClick={(event) => {
    /* ... */
  }}
>
  Click Me
</button>

Event Modifiers ​

.passive, .capture āĻāĻŦāĻ‚ .once āχāϭ⧇āĻ¨ā§āϟ āĻŽāĻĄāĻŋāĻĢāĻžāϝāĻŧāĻžāϰ⧇āϰ āϜāĻ¨ā§āϝ, āĻ•ā§āϝāĻžāĻŽā§‡āϞāϕ⧇āϏ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āχāϭ⧇āĻ¨ā§āĻŸā§‡āϰ āύāĻžāĻŽā§‡āϰ āĻĒāϰ⧇ āϏāĻ‚āϝ⧁āĻ•ā§āϤ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤

āωāĻĻāĻžāĻšāϰāĻŖ āĻ¸ā§āĻŦāϰ⧂āĻĒ:

js
h('input', {
  onClickCapture() {
    /* listener in capture mode */
  },
  onKeyupOnce() {
    /* triggers only once */
  },
  onMouseoverOnceCapture() {
    /* once + capture */
  }
})
jsx
<input
  onClickCapture={() => {}}
  onKeyupOnce={() => {}}
  onMouseoverOnceCapture={() => {}}
/>

āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āχāϭ⧇āĻ¨ā§āϟ āĻāĻŦāĻ‚ āϕ⧀ āĻŽāĻĄāĻŋāĻĢāĻžāϝāĻŧāĻžāϰ⧇āϰ āϜāĻ¨ā§āϝ, withModifiers āϏāĻžāĻšāĻžāĻ¯ā§āϝāĻ•āĻžāϰ⧀ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇:

js
import { withModifiers } from 'vue'

h('div', {
  onClick: withModifiers(() => {}, ['self'])
})
jsx
<div onClick={withModifiers(() => {}, ['self'])} />

Components ​

āĻāĻ•āϟāĻŋ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡āϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ vnode āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇, h() āĻ āĻĒāĻžāϏ āĻ•āϰāĻž āĻĒā§āϰāĻĨāĻŽ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟāϟāĻŋ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āϏāĻ‚āĻœā§āĻžāĻž āĻšāĻ“āϝāĻŧāĻž āωāϚāĻŋāϤāĨ¤ āĻāϰ āĻŽāĻžāύ⧇ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ, āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋ āύāĻŋāĻŦāĻ¨ā§āϧāύ āĻ•āϰāĻž āĻ…āĻĒā§āϰāϝāĻŧā§‹āϜāύ⧀āϝāĻŧ - āφāĻĒāύāĻŋ āϏāϰāĻžāϏāϰāĻŋ āφāĻŽāĻĻāĻžāύāĻŋ āĻ•āϰāĻž āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ:

js
import Foo from './Foo.vue'
import Bar from './Bar.jsx'

function render() {
  return h('div', [h(Foo), h(Bar)])
}
jsx
function render() {
  return (
    <div>
      <Foo />
      <Bar />
    </div>
  )
}

āφāĻŽāϰāĻž āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻšā§āĻ›āĻŋ, h āϝ⧇āϕ⧋āύ⧋ āĻĢāĻžāχāϞ āĻĢāϰāĻŽā§āϝāĻžāϟ āĻĨ⧇āϕ⧇ āφāĻŽāĻĻāĻžāύāĻŋ āĻ•āϰāĻž āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡āϰ āϏāĻžāĻĨ⧇ āĻ•āĻžāϜ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇ āϝāϤāĻ•ā§āώāĻŖ āύāĻž āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āĻŦ⧈āϧ Vue āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāĨ¤

āĻ—āϤāĻŋāĻļā§€āϞ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύāϗ⧁āϞāĻŋāϰ āϏāĻžāĻĨ⧇ āϏāĻšāϜāĻŦā§‹āĻ§ā§āϝ:

js
import Foo from './Foo.vue'
import Bar from './Bar.jsx'

function render() {
  return ok.value ? h(Foo) : h(Bar)
}
jsx
function render() {
  return ok.value ? <Foo /> : <Bar />
}

āϝāĻĻāĻŋ āĻāĻ•āϟāĻŋ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āύāĻžāĻŽ āĻĻā§āĻŦāĻžāϰāĻž āύāĻŋāĻŦāĻ¨ā§āϧāĻŋāϤ āĻšāϝāĻŧ āĻāĻŦāĻ‚ āϏāϰāĻžāϏāϰāĻŋ āφāĻŽāĻĻāĻžāύāĻŋ āĻ•āϰāĻž āύāĻž āϝāĻžāϝāĻŧ (āωāĻĻāĻžāĻšāϰāĻŖāĻ¸ā§āĻŦāϰ⧂āĻĒ, āĻāĻ•āϟāĻŋ āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋ āĻĻā§āĻŦāĻžāϰāĻž āĻŦāĻŋāĻļā§āĻŦāĻŦā§āϝāĻžāĻĒā§€ āύāĻŋāĻŦāĻ¨ā§āϧāĻŋāϤ), āĻāϟāĻŋ resolveComponent() āϏāĻžāĻšāĻžāĻ¯ā§āϝāĻ•āĻžāϰ⧀ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽā§āϝāĻžāϟāĻŋāĻ•āĻ­āĻžāĻŦ⧇ āϏāĻŽāĻžāϧāĻžāύ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤

Rendering Slots ​

āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ⧇, āĻ¸ā§āϞāϟāϗ⧁āϞāĻŋ setup() āĻĒā§āϰāϏāĻ™ā§āĻ— āĻĨ⧇āϕ⧇ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ slots āĻ…āĻŦāĻœā§‡āĻ•ā§āĻŸā§‡āϰ āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻ¸ā§āϞāϟ āĻāĻ•āϟāĻŋ āĻĢāĻžāĻ‚āĻļāύ āϝāĻž āĻ­āύ⧋āĻĄā§‡āϰ āĻāĻ•āϟāĻŋ āĻ…ā§āϝāĻžāϰ⧇ āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇:

js
export default {
  props: ['message'],
  setup(props, { slots }) {
    return () => [
      // default slot:
      // <div><slot /></div>
      h('div', slots.default()),

      // named slot:
      // <div><slot name="footer" :text="message" /></div>
      h(
        'div',
        slots.footer({
          text: props.message
        })
      )
    ]
  }
}

JSX āϏāĻŽāϤ⧁āĻ˛ā§āϝ:

jsx
// default
<div>{slots.default()}</div>

// named
<div>{slots.footer({ text: props.message })}</div>

āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ⧇, āĻ¸ā§āϞāϟāϗ⧁āϞāĻŋ this.$slots āĻĨ⧇āϕ⧇ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇:

js
export default {
  props: ['message'],
  render() {
    return [
      // <div><slot /></div>
      h('div', this.$slots.default()),

      // <div><slot name="footer" :text="message" /></div>
      h(
        'div',
        this.$slots.footer({
          text: this.message
        })
      )
    ]
  }
}

JSX equivalent:

jsx
// <div><slot /></div>
<div>{this.$slots.default()}</div>

// <div><slot name="footer" :text="message" /></div>
<div>{this.$slots.footer({ text: this.message })}</div>

Passing Slots ​

Passing children to components āĻ•āĻŋāϛ⧁āϟāĻž āĻ­āĻŋāĻ¨ā§āύāĻ­āĻžāĻŦ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇āĨ¤ āĻāĻ•āϟāĻŋ āĻ…ā§āϝāĻžāϰ⧇āϰ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤ⧇, āφāĻŽāĻžāĻĻ⧇āϰ āĻšāϝāĻŧ āĻāĻ•āϟāĻŋ āĻ¸ā§āϞāϟ āĻĢāĻžāĻ‚āĻļāύ āĻŦāĻž āĻ¸ā§āϞāϟ āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āĻāĻ•āϟāĻŋ āĻ…āĻŦāĻœā§‡āĻ•ā§āϟ āĻĒāĻžāϏ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇āĨ¤ āĻ¸ā§āϞāϟ āĻĢāĻžāĻ‚āĻļāύāϗ⧁āϞāĻŋ āĻāĻ•āϟāĻŋ āϏāĻžāϧāĻžāϰāĻŖ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ āϝāĻž āĻĢ⧇āϰāϤ āĻĻāĻŋāϤ⧇ āĻĒāĻžāϰ⧇ āϤāĻž āĻĢāĻŋāϰāĻŋāϝāĻŧ⧇ āĻĻāĻŋāϤ⧇ āĻĒāĻžāϰ⧇ - āϝāĻž āϚāĻžāχāĻ˛ā§āĻĄ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ āϏāĻ°ā§āĻŦāĻĻāĻž āĻ­āύ⧋āĻĄā§‡āϰ āĻ…ā§āϝāĻžāϰ⧇āϤ⧇ āĻ¸ā§āĻŦāĻžāĻ­āĻžāĻŦāĻŋāĻ• āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤

js
// single default slot
h(MyComponent, () => 'hello')

// named slots
// notice the `null` is required to avoid
// the slots object being treated as props
h(MyComponent, null, {
  default: () => 'default slot',
  foo: () => h('div', 'foo'),
  bar: () => [h('span', 'one'), h('span', 'two')]
})

JSX equivalent:

jsx
// default
<MyComponent>{() => 'hello'}</MyComponent>

// named
<MyComponent>{{
  default: () => 'default slot',
  foo: () => <div>foo</div>,
  bar: () => [<span>one</span>, <span>two</span>]
}}</MyComponent>

āĻĢāĻžāĻ‚āĻļāύ āĻšāĻŋāϏāĻžāĻŦ⧇ āĻ¸ā§āϞāϟ āĻĒāĻžāϏ āĻ•āϰāĻž āϤāĻžāĻĻ⧇āϰ āϚāĻžāχāĻ˛ā§āĻĄ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āĻĻā§āĻŦāĻžāϰāĻž āĻ…āϞāϏāĻ­āĻžāĻŦ⧇ āφāĻŽāĻ¨ā§āĻ¤ā§āϰāĻŖ āϜāĻžāύāĻžāύ⧋āϰ āĻ…āύ⧁āĻŽāϤāĻŋ āĻĻ⧇āϝāĻŧāĨ¤ āĻāϟāĻŋ āĻĒāĻŋāϤāĻžāĻŽāĻžāϤāĻžāϰ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤ⧇ āϏāĻ¨ā§āϤāĻžāύ⧇āϰ āĻĻā§āĻŦāĻžāϰāĻž āĻ¸ā§āϞāĻŸā§‡āϰ āύāĻŋāĻ°ā§āĻ­āϰāϤāĻž āĻŸā§āĻ°ā§āϝāĻžāĻ• āĻ•āϰāĻžāϰ āĻĻāĻŋāϕ⧇ āĻĒāϰāĻŋāϚāĻžāϞāĻŋāϤ āĻ•āϰ⧇, āϝāĻžāϰ āĻĢāϞ⧇ āφāϰāĻ“ āϏāĻ āĻŋāĻ• āĻāĻŦāĻ‚ āĻĻāĻ•ā§āώ āφāĻĒāĻĄā§‡āϟ āĻšāϝāĻŧāĨ¤

Scoped Slots ​

āĻĒā§āϝāĻžāϰ⧇āĻ¨ā§āϟ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡ āĻāĻ•āϟāĻŋ āĻ¸ā§āϕ⧋āĻĒāĻĄ āĻ¸ā§āϞāϟ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻ•āϰāϤ⧇, āĻāĻ•āϟāĻŋ āĻ¸ā§āϞāϟ āϚāĻžāχāĻ˛ā§āĻĄāϕ⧇ āĻĻ⧇āĻ“āϝāĻŧāĻž āĻšāϝāĻŧāĨ¤ āϞāĻ•ā§āĻˇā§āϝ āĻ•āϰ⧁āύ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻ¸ā§āϞāĻŸā§‡ āĻāĻ–āύ āĻāĻ•āϟāĻŋ āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāϟāĻžāϰ text āφāϛ⧇āĨ¤ āĻ¸ā§āϞāϟāϟāĻŋ āϚāĻžāχāĻ˛ā§āĻĄ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡ āĻ•āϞ āĻ•āϰāĻž āĻšāĻŦ⧇ āĻāĻŦāĻ‚ āϚāĻžāχāĻ˛ā§āĻĄ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āĻĨ⧇āϕ⧇ āĻĄā§‡āϟāĻž āĻĒā§āϝāĻžāϰ⧇āĻ¨ā§āϟ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡ āĻĒāĻžāĻ āĻžāύ⧋ āĻšāĻŦ⧇āĨ¤

js
// parent component
export default {
  setup() {
    return () => h(MyComp, null, {
      default: ({ text }) => h('p', text)
    })
  }
}

null āĻĒāĻžāϏ āĻ•āϰāϤ⧇ āĻŽāύ⧇ āϰāĻžāĻ–āĻŦ⧇āύ āϝāĻžāϤ⧇ āĻ¸ā§āϞāϟāϗ⧁āϞāĻŋāϕ⧇ āĻĒā§āϰāĻĒāϏ āĻšāĻŋāϏāĻžāĻŦ⧇ āĻ—āĻŖā§āϝ āĻ•āϰāĻž āĻšāĻŦ⧇ āύāĻžāĨ¤

js
// child component
export default {
  setup(props, { slots }) {
    const text = ref('hi')
    return () => h('div', null, slots.default({ text: text.value }))
  }
}

JSX āϏāĻŽāϤ⧁āĻ˛ā§āϝ:

jsx
<MyComponent>{{
  default: ({ text }) => <p>{ text }</p>  
}}</MyComponent>

Built-in Components ​

āĻŦāĻŋāĻ˛ā§āϟ-āχāύ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āϝ⧇āĻŽāύ <KeepAlive>, <Transition>, <TransitionGroup>, <Teleport> āĻāĻŦāĻ‚ <Suspense> āĻ…āĻŦāĻļā§āϝāχ āφāĻŽāĻĻāĻžāύāĻŋ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ⧇āϰ āϜāĻ¨ā§āϝ:

js
import { h, KeepAlive, Teleport, Transition, TransitionGroup } from 'vue'

export default {
  setup () {
    return () => h(Transition, { mode: 'out-in' }, /* ... */)
  }
}
js
import { h, KeepAlive, Teleport, Transition, TransitionGroup } from 'vue'

export default {
  render () {
    return h(Transition, { mode: 'out-in' }, /* ... */)
  }
}

v-model ​

āĻŸā§‡āĻŽāĻĒā§āϞ⧇āϟ āϏāĻ‚āĻ•āϞāύ⧇āϰ āϏāĻŽāϝāĻŧ v-model āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻŋāĻ•āĻžāϕ⧇ modelValue āĻāĻŦāĻ‚ onUpdate:modelValue āĻĒā§āϰāĻĒāϏ⧇ āĻĒā§āϰāϏāĻžāϰāĻŋāϤ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āĻ›ā§‡â€”āφāĻŽāĻžāĻĻ⧇āϰ āύāĻŋāĻœā§‡āĻĻ⧇āϰāϕ⧇ āĻāχ āĻĒā§āϰāĻĒāϗ⧁āϞāĻŋ āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇:

js
export default {
  props: ['modelValue'],
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    return () =>
      h(SomeComponent, {
        modelValue: props.modelValue,
        'onUpdate:modelValue': (value) => emit('update:modelValue', value)
      })
  }
}
js
export default {
  props: ['modelValue'],
  emits: ['update:modelValue'],
  render() {
    return h(SomeComponent, {
      modelValue: this.modelValue,
      'onUpdate:modelValue': (value) => this.$emit('update:modelValue', value)
    })
  }
}

Custom Directives ​

āĻ•āĻžāĻ¸ā§āϟāĻŽ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻžāĻŦāϞ⧀ withDirectives āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻāĻ•āϟāĻŋ vnode-āĻ āĻĒā§āϰāϝāĻŧā§‹āĻ— āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇:

js
import { h, withDirectives } from 'vue'

// a custom directive
const pin = {
  mounted() { /* ... */ },
  updated() { /* ... */ }
}

// <div v-pin:top.animate="200"></div>
const vnode = withDirectives(h('div'), [
  [pin, 200, 'top', { animate: true }]
])

āϝāĻĻāĻŋ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāύāĻžāϟāĻŋ āύāĻžāĻŽ āĻĻā§āĻŦāĻžāϰāĻž āύāĻŋāĻŦāĻ¨ā§āϧāĻŋāϤ āĻšāϝāĻŧ āĻāĻŦāĻ‚ āϏāϰāĻžāϏāϰāĻŋ āφāĻŽāĻĻāĻžāύāĻŋ āĻ•āϰāĻž āύāĻž āϝāĻžāϝāĻŧ āϤāĻŦ⧇ āĻāϟāĻŋ resolveDirective āϏāĻžāĻšāĻžāĻ¯ā§āϝāĻ•āĻžāϰ⧀ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϏāĻŽāĻžāϧāĻžāύ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤

Template Refs ​

āĻ•āĻŽā§āĻĒā§‹āϜāĻŋāĻļāύ āĻāĻĒāĻŋāφāχ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ, useTemplateRef() āĻŸā§‡āĻŽāĻĒā§āϞ⧇āϟ āϰ⧇āĻĢ āϤ⧈āϰāĻŋ āĻ•āϰāĻž āĻšāϝāĻŧ vnode-āĻ prop āĻšāĻŋāϏ⧇āĻŦ⧇ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āĻŽāĻžāύ āĻĒāĻžāϏ āĻ•āϰ⧇:

js
import { h, useTemplateRef } from 'vue'

export default {
  setup() {
    const divEl = useTemplateRef('my-div')

    // <div ref="my-div">
    return () => h('div', { ref: 'my-div' })
  }
}
Usage before 3.5

In versions before 3.5 where useTemplateRef() was not introduced, template refs are created by passing the ref() itself as a prop to the vnode:

js
import { h, ref } from 'vue'

export default {
  setup() {
    const divEl = ref()

    // <div ref="divEl">
    return () => h('div', { ref: divEl })
  }
}

āĻ…āĻĒāĻļāύ āĻāĻĒāĻŋāφāχ-āĻāϰ āϏāĻžāĻšāĻžāĻ¯ā§āϝ⧇, vnode āĻĒā§āϰāĻĒāϏ⧇ āϰ⧇āĻĢ āύāĻžāĻŽāϟāĻŋ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āĻšāĻŋāϏāĻžāĻŦ⧇ āĻĒāĻžāϏ āĻ•āϰ⧇ āĻŸā§‡āĻŽāĻĒā§āϞ⧇āϟ āϰ⧇āĻĢ āϤ⧈āϰāĻŋ āĻ•āϰāĻž āĻšāϝāĻŧ:

js
export default {
  render() {
    // <div ref="divEl">
    return h('div', { ref: 'divEl' })
  }
}

Functional Components ​

āĻ•āĻžāĻ°ā§āϝāĻ•āϰ⧀ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āĻšāϞ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡āϰ āĻāĻ•āϟāĻŋ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒ āϰ⧂āĻĒ āϝāĻžāϰ āύāĻŋāϜāĻ¸ā§āĻŦ āϕ⧋āύ⧋ āĻ…āĻŦāĻ¸ā§āĻĨāĻž āύ⧇āχāĨ¤ āϤāĻžāϰāĻž āĻŦāĻŋāĻļ⧁āĻĻā§āϧ āĻĢāĻžāĻ‚āĻļāύ āĻŽāϤ āĻ•āĻžāϜ āĻ•āϰ⧇: āĻĒā§āϰāĻĒ āχāύ, vnodes āφāωāϟ. āĻāϗ⧁āϞāĻŋ āĻāĻ•āϟāĻŋ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ āϤ⧈āϰāĻŋ āύāĻž āĻ•āϰ⧇āχ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻ•āϰāĻž āĻšāϝāĻŧ (āĻ…āĻ°ā§āĻĨāĻžā§Ž this āύāϝāĻŧ), āĻāĻŦāĻ‚ āĻ¸ā§āĻŦāĻžāĻ­āĻžāĻŦāĻŋāĻ• āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āϞāĻžāχāĻĢāϏāĻžāχāϕ⧇āϞ āĻšā§āĻ• āĻ›āĻžāĻĄāĻŧāĻžāχāĨ¤

āĻāĻ•āϟāĻŋ āĻ•āĻžāĻ°ā§āϝāĻ•āϰ⧀ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ āφāĻŽāϰāĻž āĻŦāĻŋāĻ•āĻ˛ā§āĻĒ āĻ…āĻŦāĻœā§‡āĻ•ā§āϟāϰ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤ⧇ āĻāĻ•āϟāĻŋ āĻĒā§āϞ⧇āχāύ āĻĢāĻžāĻ‚āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŋāĨ¤ āĻĢāĻžāĻ‚āĻļāύāϟāĻŋ āĻ•āĻžāĻ°ā§āϝāĻ•āϰāĻ­āĻžāĻŦ⧇ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϟāĻŋāϰ āϜāĻ¨ā§āϝ render āĻĢāĻžāĻ‚āĻļāύāĨ¤

āĻāĻ•āϟāĻŋ āĻ•āĻžāĻ°ā§āϝāĻ•āϰ⧀ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡āϰ āĻ¸ā§āĻŦāĻžāĻ•ā§āώāϰ setup() āĻšā§āϕ⧇āϰ āĻŽāϤ⧋āχ:

js
function MyComponent(props, { slots, emit, attrs }) {
  // ...
}

āϝ⧇āĻšā§‡āϤ⧁ āĻāĻ•āϟāĻŋ āĻ•āĻžāĻ°ā§āϝāĻ•āϰ⧀ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡āϰ āϜāĻ¨ā§āϝ āϕ⧋āύ⧋ this āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ āύ⧇āχ, āϤāĻžāχ Vue āĻĒā§āϰāĻĨāĻŽ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ āĻšāĻŋāϏ⧇āĻŦ⧇ props-āĻ āĻĒāĻžāϏ āĻ•āϰāĻŦ⧇:

js
function MyComponent(props, context) {
  // ...
}

āĻĻā§āĻŦāĻŋāϤ⧀āϝāĻŧ āϝ⧁āĻ•ā§āϤāĻŋ, context, āϤāĻŋāύāϟāĻŋ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āϧāĻžāϰāĻŖ āĻ•āϰ⧇: attrs, emit, āĻāĻŦāĻ‚ slotsāĨ¤ āĻāϗ⧁āϞāĻŋ āĻĻ⧃āĻˇā§āϟāĻžāĻ¨ā§āϤ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ⧇āϰ āϏāĻŽāϤ⧁āĻ˛ā§āϝ $attrs, $emit, āĻāĻŦāĻ‚ $slots āϝāĻĨāĻžāĻ•ā§āϰāĻŽā§‡āĨ¤

āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋāϰ āϜāĻ¨ā§āϝ āϏāĻžāϧāĻžāϰāĻŖ āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ⧇āĻļāύ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāϗ⧁āϞāĻŋāϰ āĻŦ⧇āĻļāĻŋāϰāĻ­āĻžāĻ— āĻ•āĻžāĻ°ā§āϝāĻ•āϰ⧀ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋāϰ āϜāĻ¨ā§āϝ āωāĻĒāϞāĻŦā§āϧ āύāϝāĻŧāĨ¤ āϝāĻžāχāĻšā§‹āĻ•, āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āĻšāĻŋāϏāĻžāĻŦ⧇ āϝ⧋āĻ— āĻ•āϰ⧇ props āĻāĻŦāĻ‚ emits āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āĻ•āϰāĻž āϏāĻŽā§āĻ­āĻŦ:

js
MyComponent.props = ['value']
MyComponent.emits = ['click']

āϝāĻĻāĻŋ props āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ•āϰāĻž āύāĻž āĻĨāĻžāϕ⧇, āϤāĻžāĻšāϞ⧇ āĻĢāĻžāĻ‚āĻļāύ⧇ āĻĒāĻžāϏ āĻ•āϰāĻž props āĻ…āĻŦāĻœā§‡āĻ•ā§āĻŸā§‡ attrs āĻāϰ āĻŽāϤ⧋āχ āϏāĻŽāĻ¸ā§āϤ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āĻĨāĻžāĻ•āĻŦ⧇āĨ¤ props āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āύāĻž āĻ•āϰāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻĒā§āϰāĻĒ āύāĻžāĻŽāϗ⧁āϞāĻŋ āĻ•ā§āϝāĻžāĻŽā§‡āϞāϕ⧇āϏ⧇ āĻ¸ā§āĻŦāĻžāĻ­āĻžāĻŦāĻŋāĻ• āĻ•āϰāĻž āĻšāĻŦ⧇ āύāĻžāĨ¤

āĻ¸ā§āĻĒāĻˇā§āϟ props āϏāĻš āĻ•āĻžāĻ°ā§āϝāĻ•āϰ⧀ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋāϰ āϜāĻ¨ā§āϝ, āĻ…ā§āϝāĻžāĻŸā§āϰāĻŋāĻŦāĻŋāωāϟ āĻĢāϞāĻĨā§āϰ⧁ āϏāĻžāϧāĻžāϰāĻŖ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋāϰ āĻŽāϤ⧋āχ āĻ•āĻžāϜ āĻ•āϰ⧇āĨ¤ āϝāĻžāχāĻšā§‹āĻ•, āĻ•āĻžāĻ°ā§āϝāĻ•āϰ⧀ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋāϰ āϜāĻ¨ā§āϝ āϝ⧇āϗ⧁āϞāĻŋ āĻ¸ā§āĻĒāĻˇā§āϟāĻ­āĻžāĻŦ⧇ āϤāĻžāĻĻ⧇āϰ props āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ•āϰ⧇ āύāĻž, āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ class, style āĻāĻŦāĻ‚ onXxx āχāϭ⧇āĻ¨ā§āϟ āĻļā§āϰ⧋āϤāĻžāϰāĻž āĻĄāĻŋāĻĢāĻ˛ā§āϟāϰ⧂āĻĒ⧇ attrs āĻĨ⧇āϕ⧇ āωāĻ¤ā§āϤāϰāĻžāϧāĻŋāĻ•āĻžāϰ āϏ⧂āĻ¤ā§āϰ⧇ āĻĒā§āϰāĻžāĻĒā§āϤ āĻšāĻŦ⧇āĨ¤ āωāĻ­āϝāĻŧ āĻ•ā§āώ⧇āĻ¤ā§āϰ⧇āχ, āĻ…ā§āϝāĻžāĻŸā§āϰāĻŋāĻŦāĻŋāωāϟ āωāĻ¤ā§āϤāϰāĻžāϧāĻŋāĻ•āĻžāϰ āύāĻŋāĻˇā§āĻ•ā§āϰāĻŋāϝāĻŧ āĻ•āϰāϤ⧇ inheritAttrs āϕ⧇ false āĻ āϏ⧇āϟ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇:

js
MyComponent.inheritAttrs = false

āĻ•āĻžāĻ°ā§āϝāĻ•āϰ⧀ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋ āϏāĻžāϧāĻžāϰāĻŖ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋāϰ āĻŽāϤ⧋āχ āύāĻŋāĻŦāĻ¨ā§āϧāĻŋāϤ āĻāĻŦāĻ‚ āĻ–āĻžāĻ“āϝāĻŧāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āĻāĻ•āϟāĻŋ āĻĢāĻžāĻ‚āĻļāύāϕ⧇ āĻĒā§āϰāĻĨāĻŽ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ āĻšāĻŋāϏ⧇āĻŦ⧇ h()-āĻ āĻĒāĻžāϏ āĻ•āϰ⧇āύ, āϤāĻžāĻšāϞ⧇ āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āĻ•āĻžāĻ°ā§āϝāĻ•āϰ⧀ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āĻšāĻŋāϏ⧇āĻŦ⧇ āĻŦāĻŋāĻŦ⧇āϚāĻŋāϤ āĻšāĻŦ⧇āĨ¤

Typing Functional Components ​

āĻ•āĻžāĻ°ā§āϝāĻ•āϰ⧀ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋ āύāĻžāĻŽ āĻŦāĻž āĻŦ⧇āύāĻžāĻŽā§€ āĻ•āĻŋāύāĻž āϤāĻžāϰ āωāĻĒāϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋ āĻ•āϰ⧇ āϟāĻžāχāĻĒ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ Vue - āĻ…āĻĢāĻŋāϏāĻŋāϝāĻŧāĻžāϞ āĻāĻ•ā§āϏāĻŸā§‡āύāĻļāύ SFC āĻŸā§‡āĻŽāĻĒā§āϞ⧇āĻŸā§‡ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ āϏāĻ āĻŋāĻ•āĻ­āĻžāĻŦ⧇ āϟāĻžāχāĻĒ āĻ•āϰāĻž āĻ•āĻžāĻ°ā§āϝāĻ•āϰ⧀ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āϟāĻžāχāĻĒ āĻšā§‡āĻ• āĻ•āϰāĻž āϏāĻŽāĻ°ā§āĻĨāύ āĻ•āϰ⧇āĨ¤

Named Functional Component

tsx
import type { SetupContext } from 'vue'
type FComponentProps = {
  message: string
}

type Events = {
  sendMessage(message: string): void
}

function FComponent(
  props: FComponentProps,
  context: SetupContext<Events>
) {
  return (
    <button onClick={() => context.emit('sendMessage', props.message)}>
        {props.message} {' '}
    </button>
  )
}

FComponent.props = {
  message: {
    type: String,
    required: true
  }
}

FComponent.emits = {
  sendMessage: (value: unknown) => typeof value === 'string'
}

Anonymous Functional Component

tsx
import type { FunctionalComponent } from 'vue'

type FComponentProps = {
  message: string
}

type Events = {
  sendMessage(message: string): void
}

const FComponent: FunctionalComponent<FComponentProps, Events> = (
  props,
  context
) => {
  return (
    <button onClick={() => context.emit('sendMessage', props.message)}>
        {props.message} {' '}
    </button>
  )
}

FComponent.props = {
  message: {
    type: String,
    required: true
  }
}

FComponent.emits = {
  sendMessage: (value) => typeof value === 'string'
}
Render Functions & JSX has loaded