其实h()函数和createVNode()函数都是创建dom节点,他们的作用是一样的,但是在VUE3中createVNode()函数的功能比h()函数要多且做了性能优化,渲染节点的速度也更快。
import { createApp } from "vue"; //import App from "./App.vue"; import { defineComponent, h, createVNode } from "vue"; import HelloWorld from "./components/HelloWorld.vue"; const img = require('./assets/logo.png'); // eslint-disable-line const App = defineComponent({ render() { return h("div", { id: "app" }, [ h("img", { src: img }), h(HelloWorld, { msg: "HelloWorld" }), createVNode("h1", { class: "hello" }, "HelloWorld") ] ); }, }); createApp(App).mount("#app");
渲染出来的结果为:
h方法是给用户来用的,它具备着多样性。我们先来写createVnode
采用二进制来标识某些东西
虚拟节点有很多,组件的、元素的和文本的
用ShapeFlags来判断是否是字符串,判断儿子children是否是个数组
children不是数组类型,则标识为text_children
将不同情况打上ShapeFlag标识
最后把来共同标识这个vode节点的类型
h(‘div') h(‘div',{style:{‘color':‘red'}},‘hello') h(‘div',‘hello') h(‘div',h(‘span')) h(‘div',[h(‘span'),h(‘span')]) h(‘div',null,‘hello',‘world') h(‘div',null,h(‘span')) h(‘div',null,[h(‘span')])
先判断参数长度
如果参数长度等于2,那么我们要区分一下第二个参数是个h方法处理过的虚拟节点,还是一个普通的属性对象,或者是一个数组
如果第二个参数是不是一个数组并且也不是一个对象,那么判断第二个参数是否是h方法处理过的虚拟节点,如果是虚拟节点,那么调用createVnode,第二个参数传null,第三个参数包装成数组。如果不是虚拟节点,那肯定就是普通属性
如果第二个参数是数组或者不是对象,第二个参数传null,直接把propsChildren传入第三个参数,传第三个参数后,都可以处理到,包括文本元素
如果参数长度大于3,后续的参数包装成一个数组
如果参数长度等于3,并且children是一个虚拟节点,children包装成一个数组
最后统一调createVnode
总结,其实我们上述的一系列判断的核心是处理传入createVnode的第三个参数,这个参数只可能是文本或者数组
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。