认识h函数
Vue推荐在绝大数情况下使用模板
来创建你的HTML,然后一些特殊的场景,你真的需要JavaScript的完全编程的能力
,这个时候你可以使用 渲染函数
,它比模板更接近编译器
;
- 前面我们讲解过VNode和VDOM的改变:
- Vue在生成真实的
DOM
之前,会将我们的节点
转换成VNode
,而VNode组合在一起形成一棵树结构,就是虚 拟DOM(VDOM)
; - 事实上,我们之前编写的
template 中的HTML
最终也是使用渲染函数
生成对应的VNode
; - 那么,如果你想充分的利用JavaScript的编程能力,我们可以自己来编写 createVNode 函数,生成对应的
VNode;
那么我们应该怎么来做呢?使用 h()函数:
- h() 函数是一个用于创建 vnode 的一个函数;
-
其实更准确的命名是 createVNode() 函数,但是为了简便在Vue将之简化为 h() 函数;
image.png
h()函数 如何使用呢?它接受三个参数:
image.png
注意事项:
- 如果没有props,那么通常可以将children作为第二个参数传入;
- 如果会产生歧义,可以将null作为第二个参数传入,将children作为第三个参数传入;
例: render函数的基本使用
<script>
import { h } from "vue"
export default {
//render函数是optionsApi的一个选项,此函数返回Vnode
render() {
//h函数返回VNode
return h("h1", {class: "h1"}, "今天天气不错")
}
}
</script>
例: optionsApi实现计数器
<script>
import {h} from 'vue'
export default {
data() {
return {
counter: 100
}
},
render() {
// render函数中绑定了this
//ref对象可以自动解包
return h('div', {class: 'counter'}, [
h('h1', null, `当前计数: ${this.counter}`),
h('button', {
onClick: () => this.counter++
}, '+1'),
h('button', {
onClick: () => this.counter--
}, '-1')
])
}
}
</script>
<style lang="scss" scoped>
</style>
例: compositionApi实现计数器
<script>
import { h, ref } from "vue";
export default {
setup() {
const counter = ref(100);
//setup函数返回一个render函数,render函数返回vnode
return () => {
return h("div", { class: "counter" }, [
h("h1", null, `当前计数: ${counter.value}`),
h(
"button",
{
onClick: () => counter.value++,
},
"+1"
),
h(
"button",
{
onClick: () => counter.value--,
},
"-1"
),
]);
};
},
};
</script>
<style lang="scss" scoped></style>
render函数中插槽的使用
例: optionsApi的render函数中插槽的使用
App.vue
<script>
import { h } from "vue";
import HelloWorld from "./HelloWorld.vue";
// render函数写法,因为不是在template中使用,导入的组件不需要注册,可以直接使用
export default {
render() {
return h("div", { class: "app" }, [
h("h1", null, "我是App组件"),
//给HelloWorld只插入一个插槽,h函数的第三个参数可以写成一个对象,如果插入多个插槽,h函数的第三个参数写成对象数组
h(HelloWorld, null, {
// 插槽是一个函数,调用的时候返回VNode
default: (props) => h("div", null, `我的名字是${props.name}`),
}),
]);
},
};
</script>
<style lang="scss" scoped></style>
Home.vue
<script>
import { h } from "vue";
export default {
render() {
return h("div", { class: "hello_world" }, [
h("h1", null, "hello world"),
// 通过this.$slots可以拿到此子组件在父组件中被使用时,插入的所有插槽,this.$slots是一个对象,存储着所有的插槽
//插槽是一个函数,调用的时候返回VNode,可以在调用的时候传参,
this.$slots.default
? this.$slots.default({ name: "coderwhy" })
: h("span", null, "我是HelloWorld组件的默认插槽"),
]);
},
};
</script>
<style lang="scss" scoped></style>
例: compositionApi的render函数中插槽的使用
App.vue
<script>
import { h } from "vue";
import HelloWorld from "./HelloWorld.vue";
// render函数写法,因为不是在template中使用,导入的组件不需要注册,可以直接使用
export default {
setup() {
return () => {
return h("div", { class: "app" }, [
h("h1", null, "我是App组件"),
//给HelloWorld只插入一个插槽,h函数的第三个参数可以写成一个对象,如果插入多个插槽,h函数的第三个参数写成对象数组
h(HelloWorld, null, {
// 插槽是一个函数,调用的时候返回VNode
default: (slotProps) => h("div", null, `我的名字是${slotProps.name}`),
}),
]);
};
},
};
</script>
<style lang="scss" scoped></style>
Home.vue
<script>
import { h } from "vue";
export default {
setup(props, { slots }) {
return () => {
return h("div", { class: "hello_world" }, [
h("h1", null, "hello world"),
// 通过slots可以拿到此子组件在父组件中被使用时,插入的所有插槽,this.$slots是一个对象,存储着所有的插槽
//插槽是一个函数,调用的时候返回VNode,可以在调用的时候传参,
slots.default
? slots.default({ name: "coderwhy" })
: h("span", null, "我是HelloWorld组件的默认插槽"),
]);
};
},
};
</script>
<style lang="scss" scoped></style>
image.png
此文档主要内容来源于王红元老师的vue3+ts视频教程
网友评论