首先我们回顾一下在脚本中利用createVNode和render函数创建Vue节点的方法
<template></template>
<script setup lang="ts">
import { ref, reactive, createVNode, render } from 'vue'
// 类型、配置项、内容
const div = createVNode('div', { id: 'foo' }, '小满')
// 虚拟DOM、要插入的位置
render(div, document.body)
</script>
<style scoped></style>
这种方法可以很方便地创建节点,样式可以使用tailwindcss(好像不能用普通css)。不过以下这种h函数提供了全新的方法(仍需借助tailwindcss)
<template>
<Btn @on-click="getBtn" text="小满的帽子"> </Btn>
</template>
<script setup lang="ts">
import { ref, reactive, h } from 'vue'
type Props = {
text: string
}
// 要定义的节点名称
const Btn = (props: Props, ctx: any) => {
return h(
'div',
{
class: [
'rounded',
'bg-green-500',
'text-gray-50',
'text-center',
'p-1.5',
],
id: ['a'],
// 这里的onClick指的是原生事件,意为当Btn标签被点击时触发onClick的回调函数
onClick: () => {
ctx.emit('on-click', '开枪')
},
},
props.text
)
}
const getBtn = (str: string) => {
console.log(str)
}
</script>
<style scoped></style>
如图,要定义的节点不再是函数的返回值,它本身就是一个函数。这个函数接收两个变量(props和ctx),props是从模板当中获取到的数据,ctx中包含了emit、slots等vue常用的函数,h函数的参数列表和createVNode相同,都是标签类型{string}--id、类名、事件等标签属性{配置对象}---标签中展示的内容
除上述用法外,标签中也可以定义插槽,只需要在上述模板的基础上将props.text改为ctx.slots.插槽名()即可
<template>
<Btn @on-click="getBtn" text="小满的帽子">
<!-- 这里填写对应的插槽名称 -->
<template #default>
小满要拔剑了!
</template>
</Btn>
</template>
<script setup lang="ts">
import { ref, reactive, h } from 'vue'
type Props = {
text?: string
}
// 要定义的节点名称
const Btn = (props: Props, ctx: any) => {
return h(
'div',
{
class: [
'rounded',
'bg-green-500',
'text-gray-50',
'text-center',
'p-1.5',
],
id: ['a'],
onClick: () => {
ctx.emit('on-click', '开枪')
},
},
ctx.slots.default()
)
}
const getBtn = (str: string) => {
console.log(str)
}
</script>
<style scoped></style>