[vue 번역] 렌더 함수 & JSX (Render Functions & JSX)
기본 사용법 (Basic Usage)
Vue는 템플릿을 사용하여 대부분의 경우 UI를 구축하는 것을 권장합니다. 그러나 JavaScript의 완전한 프로그래밍 능력이 필요한 경우가 있습니다. 이때 렌더 함수(render function)를 사용할 수 있습니다.
렌더 함수는 컴포넌트의 렌더링 출력을 프로그래밍 방식으로 정의하는 방법입니다. 템플릿과 달리, 렌더 함수는 컴파일 단계가 필요하지 않으며, JavaScript 코드 내에서 직접 작성됩니다.
h()
함수
Vue는 가상 노드(VNode)를 생성하기 위한 h()
함수를 제공합니다. h()
는 "hyperscript"의 약자로, "HTML을 생성하는 스크립트"를 의미합니다. h()
함수는 세 개의 인자를 받습니다:
- 타입: HTML 태그 이름, 컴포넌트 또는 비동기 컴포넌트.
- Props: 속성, props, 이벤트 리스너를 포함하는 객체.
- 자식: 문자열 또는 VNode 배열.
import { h } from 'vue'
export default {
render() {
return h(
'h1',
{
class: 'title'
},
'Some title'
)
}
}
렌더 함수 구현하기 (Implementing Render Functions)
렌더 함수는 setup()
훅 내에서 직접 반환될 수 있습니다:
import { ref, computed, h } from 'vue'
export default {
props: {
/* ... */
},
setup(props, { slots, emit }) {
const count = ref(1)
// 렌더 함수 반환
return () => h('div', count.value)
}
}
VNode
h()
함수는 VNode를 반환합니다. VNode는 특정 속성을 가진 일반 객체이며, Vue가 실제 DOM 노드를 생성하는 데 사용하는 정보를 포함합니다.
제어 흐름 (Control Flow)
템플릿의 v-if
및 v-for
와 달리, 렌더 함수에서는 일반 JavaScript를 사용하여 제어 흐름을 구현할 수 있습니다.
// v-if
if (isEditing) {
return h('input', { value: text.value })
} else {
return h('p', text.value)
}
// v-for
return h(
'ul',
items.map((item) => h('li', item.name))
)
JSX / TSX
JSX는 XML과 유사한 구문을 사용하여 JavaScript 내에서 UI를 작성할 수 있게 해주는 JavaScript의 확장입니다. Vue는 JSX를 사용하여 컴포넌트를 작성하는 것을 지원합니다.
import { ref, computed } from 'vue'
export default {
props: {
/* ... */
},
setup(props) {
const count = ref(1)
return () => <div>{count.value}</div>
}
}
JSX 설정하기
JSX를 사용하는 프로젝트는 일반적으로 Vite 또는 Vue CLI와 같은 빌드 도구를 통해 사전 구성됩니다. @vitejs/plugin-vue-jsx
플러그인을 사용하여 Vite 프로젝트에서 JSX를 활성화할 수 있습니다.
렌더 함수 레시피 (Render Function Recipes)
v-if
// 템플릿
<div v-if="ok">yes</div>
<span v-else>no</span>
// 렌더 함수
h(ok.value ? 'div' : 'span', ok.value ? 'yes' : 'no')
v-for
// 템플릿
<ul>
<li v-for="{ id, text } in items" :key="id">{{ text }}</li>
</ul>
// 렌더 함수
h('ul', items.value.map(({ id, text }) => h('li', { key: id }, text)))
v-on
on
접두사가 붙고 카멜케이스로 된 props를 사용하여 이벤트 핸들러를 전달합니다. 예를 들어, @click
은 onClick
이 됩니다.
h('button', {
onClick: () => console.log('clicked')
})
컴포넌트
컴포넌트 VNode를 생성하려면, h()
의 첫 번째 인자로 가져온 컴포넌트 정의를 전달합니다.
import MyComponent from './MyComponent.vue'
h(MyComponent, {
// props 전달
msg: 'hello'
})
슬롯
슬롯은 slots
객체를 통해 접근할 수 있습니다. 각 슬롯은 VNode 배열을 반환하는 함수입니다.
// default 슬롯 렌더링
slots.default()
// 이름 있는 슬롯 렌더링
slots.header()
v-model
v-model
디렉티브는 렌더 함수에서 modelValue
와 onUpdate:modelValue
props로 확장됩니다.
함수형 컴포넌트 (Functional Components)
함수형 컴포넌트는 자체 상태가 없는 컴포넌트입니다. 일반 함수처럼 정의됩니다. 첫 번째 인자는 props
이고 두 번째 인자는 slots
, attrs
, emit
을 포함하는 컨텍스트 객체입니다.
function MyComponent(props, { slots, attrs, emit }) {
// ...
}