利用h函数编写组件
前言
h 函数 hyperscript
(生成 script)用于生成对应的标签
其实所有的 vue
组件都是经过一次 render
之后转化成 h 函数,然后再去对应的渲染 dom
的。那么使用 h 函数渲染组件有什么优势呢?
sfc 结构
vue
是使用了一段叫做 sfc
的结构,类似于一开始学习前端的时候 body script style
,现在 vue
是 template script style
1 | <template> |
而在 template
结构种的 html
代码 最后会被转化为 h
函数,如下
1 | h("div", { class: "example" }, msg); |
Vue
通过这个 h
函数去真实的渲染 dom
,和虚拟节点的 diff
对比等
如何编写 h 函数
h
函数接收的参数是根据使用者传入的参数决定的,下面只介绍重要的几个部分(有十九种,一般不可能都使用上)
- 参数一
type
: 可以写一个标签或者component
例如
1 | h("div", "this is a div tag"); |
- 可选参数二
props
: 用于给标签或者component
传递props
,一般是对象形式 可以结合 tw 等 css 使用,可以写事件监听器,注意使用on
前缀
1 | h("div", { class: "h-full w-full text-[grey]" }); |
- 可选参数三
children
:字符串|number|对象类型 用于渲染子节点 注意子节点也可以是 h 函数生成的节点,可以模拟v-if
的操作
1 | h("div", "this is a div tag"); |
注意
一开始编写 h
函数的时候,传递了 type
之后 默认是以下可以直接传递 children
的类型,也就是 h
函数的后续参数是根据用于用户传递的值的类型去判断的
这也就是为什么 prop
是对象类型 而 children
是 string | number | array
类型了 因为方便判断
在 ts/js 中编写 component
其实很早之前就有一个疑问,就是 component
是否可以直接在 javascript
文件里面编写,因为有点时候,只是一点点的内容,其实完全不需要写成一个 vue
文件,需求例如:
在表格上面的某一项,默认显示对应的文本,当点击的时候渲染一个 input
框
然后 blur
或者 change
事件触发的时候 去调用后台接口改变该项的值
如果写成一个 vue
文件 大致上长这样(可能会写错 但大致是这样的)
1 | <template> |
实际上 做的功能很少 但写起来总感觉 没有必要装成一个 vue
文件 因为最后都是渲染成 h
函数 那为什么不直接写 h
函数呢?
defineComponent = 渲染组件 = 渲染一个带状态的 h 函数
我们利用 defineComponent
这个函数 对应渲染组件
其中他有一个状态 props
和 原来的 props
是一样的
还有一个 setup
函数 也是一样的 接收 props
然后返回一个虚拟节点 也就是我们 html
上的内容
这样有了 setup
函数 我们就有了状态的编写 就大于单独编写 h
函数的作用了
1 | const editableInputComponent = defineComponent({ |
结论就是 defineComponent
就是渲染组件 也就是执行一个带了自我状态的 h
函数defineComponent
= 渲染组件 = 渲染一个带状态的 h
函数
PropType
有个小细节 因为 defineComponent
的 props
不能很明确的定义 接收到的数据类型
所以使用了 PropType
去拓展他的类型 例如下面把 Function
拓展成接收一个参数类型为 string
,返回值为空的函数
1 | props: { |
但需要注意的是是 如果多类型定义 是不能使用 PropType
的
1 | props: { |
建议改为
1 | type selectVal = string | string[] |
或者直接使用
拓展
关于 h
函数 实操的过程中还是会遇到不知道怎么写的情况,比如不知道怎么写自定义指令,不知道怎么写 v-model
等
可以参考这篇文章:https://www.lanmper.cn/vue/t9645
结语
要用 h
函数封装组件还是直接写组件去封装 各有利弊 h
函数需要更多的学习成本,如果组件库支持 render
函数编写肯定是更高的,比如 Naive
组件库,优势就是完全函数式编程,适用于不太需要 css
和 html
的情况。封装 vue
组件的话,就是能够更方便的编写 html
和 css
,缺点就是可能会很冗余。
主要记住一句话:高粒度的封装无法适应低粒度的变化。谨慎封装!