大家好,欢迎来到IT知识分享网。
当template内部的结构代码在编译的时候发生了什么?
比如我们下面的代码
1 <template> 2 <div> 3 <h1>123456789</h1> 4 </div> 5 </template>
我们平常写template里面所使用的模板是HTML语法组件的页面,其实在vue中都会被编译为render函数,因为vue中采用的是虚拟dom进行页面组件,这样的优点是优化页面的加载重绘性能
render函数的基本使用
我们在views文件夹中新建一个Render.vue组件,注意如果要使用render函数编译模板,一定不要有<template></template>,否则就回加载template中的内容
render.vue
1 <script> 2 export default { 3 render(createElement){ 4 return createElement('h1',{},123456789) 5 } 6 } 7 </script> 8 9 <style lang="scss" scoped> 10 </style>
App.vue
1 <template> 2 <div> 3 <render></render> 4 </div> 5 </template> 6 <script> 7 import render from "./views/render.vue" 8 export default { 9 components:{ 10 render 11 } 12 } 13 </script> 14 <style lang="less" scoped> 15 </style>
我们设置一个小案例,通过render函数动态的修改当前组件的节点渲染
1 <script> 2 export default { 3 props:{ 4 tag:{ 5 type:String, 6 required:true, 7 }, 8 data:{ 9 type:String 10 } 11 }, 12 render(createElement){ 13 return createElement(this.tag,{},this.data) 14 } 15 } 16 </script> 17 18 <style lang="scss" scoped> 19 </style>
props有两个值,第一个值为tag,指的是传入的节点名称,第二个值data,就是要渲染的节点内容
App.vue
1 <template> 2 <div> 3 <render :tag="'p'" :data="'123456789'"></render> 4 </div> 5 </template>
此时要注意,如果没有设置的元素节点,render函数也会加载
1 <render :tag="'aaaaa'" :data="'123456789'"></render>
这样做有一个好处,就是如果我们的节点是一个ui元素名称,或者是自定义组件,都会被识别
比如我们引入的是element-ui
1 <render :tag="'el-button'" :data="'我是button'"></render>
也可以设置组件内容
1 <script> 2 import son from "./son.vue" 3 export default { 4 props:{ 5 tag:{ 6 type:String, 7 required:true, 8 }, 9 data:{ 10 type:String 11 } 12 }, 13 render(createElement){ 14 return createElement(son,{},this.data) 15 } 16 } 17 </script> 18 <style lang="scss" scoped> 19 </style>
createdElement函数一共有三个参数,第一个参数我们已经知道如何使用,第二个参数其实就是对当前的节点(组件)的属性描述
1 <script> 2 export default { 3 props:{ 4 tag:{ 5 type:String, 6 required:true, 7 }, 8 data:{ 9 type:String 10 } 11 }, 12 render(createElement){ 13 return createElement(this.tag,{ 14 class:'color_red' 15 },this.data) 16 } 17 } 18 </script> 19 <style scoped> 20 .color_red{ 21 color: red; 22 } 23 </style>
我们设置class颜色为red
还可以用domProps设置
1 render(createElement){ 2 return createElement(this.tag,{ 3 // class:'color_red' 4 //Dom的prototype 5 domProps:{ 6 className:'color-red', 7 innerHTML:'123456789' 8 } 9 },this.data) 10 }
最重要的是第三个参数,第三个参数如果不是数组,则表示渲染内容,否则,如果设置了数组,内部必须是createElement函数,代表的是当前的元素再进行嵌套
1 render(createElement){ 2 return createElement(this.tag,{ 3 // class:'color_red' 4 //Dom的prototype 5 domProps:{ 6 className:'color-red', 7 8 } 9 },[createElement('p', [createElement('span', '我是p元素内部的span元素')]), createElement('p', '我是p元素')]) 10 }
createElement方法的核心其实就是第三个参数,因为这个参数最大的魔力就是能够嵌套,由于之前能够通过第二个参数设置当前元素的相关属性,所以如果一旦第三个参数实现了嵌套元素的功能,此时就可以实现通过js设置HTML模板
render函数还有一个最大的功能就是解析模板
此时我们的render函数,并没有通过字符串设置模板内容,而是直接设置了对应的元素
1 render(){ 2 return ( 3 <div> 4 <h2>四大名著</h2> 5 <ul> 6 <li>西游记</li> 7 <li>水浒传</li> 8 <li>三国演义</li> 9 <li>红楼梦</li> 10 </ul> 11 </div> 12 ) 13 }
页面中进行了识别和解析
createElement源码解析
我们先创建一个类似于createElement的结构
1 var vDom=createElement('div',{class:'container'},[ 2 createElement('p',{class:'item',style:'color:red'},'我是p节点1'), 3 createElement('p',{class:'item',style:'background:blue'},'我是p节点2'), 4 createElement('p',{class:'item'},'我是p节点3'), 5 createElement('input',{value:'我是value'},'我是input'), 6 ])
创建Element构造函数
1 function Element(type,props,children){ 2 this.type=type; 3 this.props=props; 4 this.children=children; 5 6 } 7 function createElement(type,props,children){ 8 return new Element(type,props,children) 9 }
创建节点和属性
1 function render(obj){ 2 //创建节点 3 let el=document.createElement(obj.type); 4 //给相关的节点设置对应的属性 5 for(let key in obj.props){ 6 el.setAttribute(key,obj.props[key]) 7 }; 8 if(Array.isArray(obj.children)){ 9 //遍历创建子元素 10 obj.children.forEach((child)=>{ 11 // console.log(child) 12 //递归操作,如果当前的child不是文本节点,就继续进行递归操作,否则渲染文本节点 13 child=child instanceof Element?render(child):document.createTextNode(child); 14 //节点上树 15 el.appendChild(child) 16 }) 17 //当前obj.children如果不是数组而是字符串,就当做文本进行渲染 18 }else if (typeof obj.children==='string'){ 19 el.appendChild(document.createTextNode(obj.children)) 20 } 21 return el 22 }
渲染页面
1 function renderDom(el,target){ 2 target.appendChild(el) 3 }
调用
1 renderDom(render(vDom),document.getElementById("app"))
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30392.html