学习了coderwhy的vue3+ts视频课的笔记
1. 认识h函数
- Vue推荐在绝大数情况下使用模板来创建你的HTML,然后一些特殊的场景,你真的需要JavaScript的完全编程的能力,这个时候你可以使用 渲染函数,它比模板更接近编译器;
- 前面我们讲解过VNode和VDOM的改变(跳转链接)
- Vue在生成真实的DOM之前,会将我们的节点转换成VNode,而VNode组合在一起形成一颗树结构,就是虚拟DOM(VDOM);
- 事实上,我们之前编写的 template 中的HTML 最终也是使用渲染函数生成对应的VNode;
- 那么,如果你想充分的利用JavaScript的编程能力,我们可以自己来编写 createVNode 函数,生成对应的 VNode。
- 那么我们应该怎么来做呢?使用 h()函数:
- h() 函数是一个用于创建 vnode 的一个函数;
- 其实更准备的命名是 createVNode() 函数,但是为了简便在Vue将之简化为 h() 函数。
2. h()函数如何使用呢?
- h()函数 如何使用呢?它接受三个参数:
- 注意事项:
- 如果没有props,那么通常可以将children作为第二个参数传入;
- 如果会产生歧义,可以将null作为第二个参数传入,将children作为第三个参数传入。
3. h函数的基本使用
- h函数可以在两个地方使用:
- render函数选项中;
- setup函数选项中(setup本身需要是一个函数类型,函数再返回h函数创建的VNode)。
// .vue文件
<script>
import { h } from 'vue';
export default {
render() {
return h("h2", {class: "title"}, "Hello Render")
}
}
</script>
<style scoped>
</style>
4. h函数计数器案例
// .vue文件
<script>
import { h } from 'vue';
export default {
data() {
return {
counter: 0
}
},
render() {
return h("div", {class: "app"}, [
h("h2", null, `当前计数: ${this.counter}`),
h("button", {
onClick: () => this.counter++
}, "+1"),
h("button", {
onClick: () => this.counter--
}, "-1"),
])
}
}
</script>
<style scoped>
</style>
// .vue文件——setup()
<script>
import { ref, h } from 'vue';
export default {
setup() {
const counter = ref(0);
return () => {
return h("div", {class: "app"}, [
h("h2", null, `当前计数: ${counter.value}`),
h("button", {
onClick: () => counter.value++
}, "+1"),
h("button", {
onClick: () => counter.value--
}, "-1"),
])
}
}
}
</script>
<style scoped>
</style>
5. 函数组件和插槽的使用
// App.vue
<script>
import { h } from 'vue';
import HelloWorld from './HelloWorld.vue';
export default {
render() {
return h("div", null, [
h(HelloWorld, null, {
default: props => h("span", null, `app传入到HelloWorld中的内容: ${props.name}`)
})
])
}
}
</script>
<style scoped>
</style>
// HelloWorld.vue
<script>
import { h } from "vue";
export default {
render() {
return h("div", null, [
h("h2", null, "Hello World"),
this.$slots.default ? this.$slots.default({name: "coderwhy"}): h("span", null, "我是HelloWorld的插槽默认值")
])
}
}
</script>
<style lang="scss" scoped>
</style>
6. jsx
和上面的代码相比较,下面的代码逻辑更加清晰明了。
// App.vue
<script>
import HelloWorld from './HelloWorld.vue';
export default {
data() {
return {
counter: 0
}
},
render() {
const increment = () => this.counter++;
const decrement = () => this.counter--;
return (
<div>
<h2>当前计数: {this.counter}</h2>
<button onClick={increment}>+1</button>
<button onClick={decrement}>-1</button>
<HelloWorld>
</HelloWorld>
</div>
)
}
}
</script>
<style lang="scss" scoped>
</style>
// HelloWorld.vue
<script>
export default {
render() {
return (
<div>
<h2>HelloWorld</h2>
{this.$slots.default ? this.$slots.default(): <span>哈哈哈</span>}
</div>
)
}
}
</script>
<style scoped>
</style>