1。如前所述,Vue.js框架的很多功能都依赖于渲染器的实现,渲染器也是框架性能的核心,可以直接影响到框架的性能。在这方面,Vue.js3渲染器使用编译器提供的信息通过快捷路径更新来提高性能。2.渲染器和响应系统的结合。渲染器用于执行渲染任务。可以在浏览器平台上渲染真实的DOM元素,也可以实现框架的跨平台能力。反应性的源码之前已经实现了。为了后续操作讲解方便,可以直接使用vue.js3的源码导入使用。以便可以通过公开的API使用它:const{effect,ref}=Vue反应性;functionrenderer(domString,container){container.innerHTML=domString;}constcount=ref(1);effect(()=>{renderer(`
${count.value}
`,document.getElementById("app"))});count.value++渲染器将虚拟DOM节点渲染成真实DOM节点的过程称为挂载。在Vue中,挂载完成后会触发mounted钩子函数,从而实现虚拟DOM加载的挂载。另外,渲染器还需要一个挂载点作为参数来指定具体的挂载位置,渲染器会使用这个DOM元素作为容器元素来渲染内容。在Vue.js3中,渲染器是通过createRenderer函数创建的,渲染器不仅包括渲染器函数render,还包括用于服务端渲染的hydrate函数。用于创建应用程序的createApp函数也是渲染器的一部分。constrenderer=createRenderer();//第一次渲染renderer.render(oldVNode,document.querySelector("#app"));//第二次渲染renderer.render(newVNode,document.querySelector("#app"));在上面的代码,首先调用createRenderer函数创建一个renderer,通过调用renderer的renderer.render函数创建一个新的DOM元素,然后将虚拟DOM节点vnode渲染到挂载点,也就是mount。在同一个挂载的DOM上,当调用renderer.render函数进行渲染时,渲染器除了实现常规的DOM挂载外,还需要进行页面更新操作,即DOM更新。在渲染器中,vnode会与上次渲染的oldVNode进行比较,找出并更新变化点。这个过程称为“补丁”(patch)或更新。functioncreateRenderer(){functionrender(domString,container){if(vnode){//新的vnode存在,将它和旧的vnode传递给patch函数进行patchingpatch(container._vnode,vnode,container);}else{if(container._vnode){//如果旧节点vnode存在,需要清除挂载点的DOM元素container.innerHTML="";}}//将vnode存入container._vnodecontainer._vnode=vnode}return{render}}上面代码中是render函数的基本实现。patch函数是整个渲染器的核心入口,承载着最重要的渲染逻辑。patch(n1,n2,container){/***/}n1:旧的VNode。n2:新的VNode。容器:挂载容器。3.自定义渲染器下面看看如何自定义渲染器的实现来实现跨平台的能力,那就从普通的h1标签说起吧。constvnode={type:"h1",children:"pingping"}在上面的代码中实现了一个简单的vnode,使用type属性来描述vnode类型,当type属性为字符串类型值时,就是一个普通的标签。constvnode={type:"h1",children:"pingping"}constrenderer=createRenderer();//第一次渲染renderer.render(vnode,document.querySelector("#app"));这样,我们就可以渲染为
pingping
,为了完成渲染工作,可以在下面添加patch函数。functioncreateRenderer(){functionpatch(n1,n2,container){//如果n1不存在,则表示挂载,需要调用mountElement函数完成挂载if(!n1){mountElement(n2,container);}else{//n1存在,即打补丁更新DOM节点}}functionrender(domString,container){if(vnode){//新的vnode存在,将它和旧的vnode传给patch函数进行修补补丁(容器._vnode,vnode,容器);}else{if(container._vnode){//如果老节点vnode存在,需要清除挂载点的DOM元素container.innerHTML="";}}//将vnode存入container._vnodeincontainer._vnode=vnode}return{render}}上面代码中,如果patch函数中的参数n1不存在,说明没有老的VNode,而你只需要在这个时候挂载它。functionmountElement(vnode,container){constel=document.createElement(vnode.type);if(typeofvnode.children==="string"){el.textContent=vnode.children;}container.appendChild(el);}在上面的代码中,简单的实现了一个普通标签元素的挂载工作。Vue.js3是一个跨平台框架,得益于独立于平台的通用渲染器,并且在mountElement函数中依赖大量浏览器API。如果你想设计一个通用的渲染器,你必须剥离与平台相关的API。当然,你可以将这些操作DOM的API作为createRenderer的配置项。constrenderer=createRenderer({//创建元素createElement(tag){returndocument.createElement(tag);},//设置元素的文本节点setElementText(el,text){el.textContent=text;},//useToaddaspecifiedelementtoaspecifiedparentnodeinsert(el,parent,achor=null){parent.insertBefore(el,anchor);}})在上面的代码中,可以将操作DOM的API封装成一个object并将其传递给createRenderer函数,就可以通过配置项获取操作DOM的API。functioncreateRenderer(options){const{createElement,setElementText,insert}=options;functionmountElement(vnode,container){constel=createElement(vnode.type);if(typeofvnode.children==="string"){setElementText(el,vnode.children)}insert(el,container);}functionpatch(n1,n2,container){//...}functionrender(domString,container){//...}return{render}}现在我们对自定义渲染器有了更深入的了解。自定义渲染器不是黑盒子。他们只是通过代码抽象将核心代码抽象出来,让核心代码不再强依赖于平台特定的API,通过自定义配置项实现跨平台。4.写在最后在这篇文章中,我们了解了渲染器的作用和实现,知道它是将虚拟DOM转换为真实DOM挂载到节点上,更新节点时通过patch实现。为了实现跨平台渲染,用户需要自定义配置项渲染器来实现DOM渲染和挂载。