在 Vue 3 中,渲染函数(render function)提供了一种编程方式来描述组件的输出,而不是使用模板语法。渲染函数在处理复杂的动态内容或在 JSX 语法更合适的场景中非常有用。
使用方法
- 在 Vue 3 中使用渲染函数,可以通过
h
函数来创建虚拟节点(VNode)
//这里我们使用 h 函数创建了一个 div 元素,并将其内容设置为 'Hello, Vue 3 Render Function!'
<template>
<div id="app"></div>
</template>
<script setup>
import { h } from 'vue'
const MyComponent = {
setup() {
return () => h('div', { class: 'hello' }, 'Hello, Vue 3 Render Function!')
}
}
</script>
- JSX 语法:在 Vue 3 中也可以使用 JSX 语法,它与 React 中的 JSX 语法非常相似。
首先需要安装 Babel 插件:
npm install @vitejs/plugin-vue-jsx -D
然后在 vite.config.js
中配置:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
export default defineConfig({
plugins: [vue(), vueJsx()]
})
然后就可以在组件中使用 JSX:
<script setup>
import { defineComponent } from 'vue'
const MyComponent = defineComponent({
setup() {
return () => <div class="hello">Hello, Vue 3 JSX!</div>
}
})
export default MyComponent
</script>
使用场景
- 动态创建复杂的结构
<template>
<div id="app"></div>
</template>
<script setup>
import { h } from 'vue'
const MyComponent = {
setup() {
const createList = () => {
return h('ul', null,
[1, 2, 3].map(num =>
h('li', { key: num }, `Item ${num}`)
)
)
}
return () => h('div', { class: 'list-container' }, createList())
}
}
</script>
- JSX 语法的使用场景
使用 JSX 语法可以更方便地与 JavaScript 集成,尤其是在有复杂逻辑或需要使用 JavaScript 表达式时:
<script setup>
import { defineComponent } from 'vue'
const MyComponent = defineComponent({
setup() {
const items = [1, 2, 3]
return () => (
<div class="list-container">
<ul>
{items.map(item => (
<li key={item}>Item {item}</li>
))}
</ul>
</div>
)
}
})
export default MyComponent
</script>
- 与第三方库的集成
当需要与第三方库进行集成时,渲染函数提供了一种直接的方式来创建和操作 DOM 元素。例如,使用 D3.js 创建图表:
<template>
<div id="app"></div>
</template>
<script setup>
import { onMounted } from 'vue'
import * as d3 from 'd3'
const MyComponent = {
setup() {
onMounted(() => {
const svg = d3.select('#app')
.append('svg')
.attr('width', 200)
.attr('height', 200)
svg.append('circle')
.attr('cx', 100)
.attr('cy', 100)
.attr('r', 50)
.attr('fill', 'blue')
})
return () => h('div', { id: 'app' })
}
}
</script>
总结
渲染函数在以下场景中非常有用:
- 动态创建复杂的结构:提供了更大的灵活性,可以通过编程方式创建和操作虚拟 DOM。
- 使用 JSX 语法:更方便地与 JavaScript 集成,适合在有复杂逻辑或需要使用 JavaScript 表达式的场景。
- 与第三方库的集成:直接创建和操作 DOM 元素,方便集成如 D3.js 这样的第三方库。
渲染函数是 Vue 提供的强大工具,当模板语法不够用时,可以考虑使用渲染函数来实现复杂的需求。
完整示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue 3 Render Function with Styles</title>
<script src="https://unpkg.com/vue@3.2.47"></script>
<style>
/* 定义一些全局样式 */
.custom-class {
font-family: Arial, sans-serif;
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
}
.button-class {
background-color: #4CAF50;
color: white;
padding: 10px 20px;
border: none;
cursor: pointer;
border-radius: 8px;
}
.button-class:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<div id="app"></div>
<script>
const { createApp, defineComponent, h, ref } = Vue;
// 定义第一个自定义组件
const CustomComponent = defineComponent({
props: ['message'],
render () {
return h('div', { class: 'custom-class' }, [
h('h1', 'Hello from CustomComponent!'),
h('p', this.message)
]);
}
});
// 定义第二个自定义组件
const CustomComponent2 = defineComponent({
props: ['message'],
render () {
return h('div', { class: 'custom-class' }, [
h('h1', 'Hello from CustomComponent2!'),
h('h1', {
style: { color: 'red' }
}, this.message)
]);
}
});
// 创建 Vue 应用
const App = defineComponent({
setup () {
const msg = ref('This is the initial message.');
const showSecondComponent = ref(false);
const updateMessage = () => {
msg.value = 'The message has been updated!';
showSecondComponent.value = !showSecondComponent.value;
};
return { msg, showSecondComponent, updateMessage };
},
render () {
return h('div', [
this.showSecondComponent
? h(CustomComponent2, { message: this.msg })
: h(CustomComponent, { message: this.msg }),
h('button', {
class: 'button-class',
onClick: this.updateMessage,
style: { marginTop: '10px' }
}, 'Toggle Component')
]);
}
});
// 挂载 Vue 应用
createApp(App).mount('#app');
</script>
</body>
</html>