render函数

render函数当template内部的结构代码在编译的时候发生了什么?比如我们下面的代码1<template>2<div>3<h1>123456789</h1>4</div>5</template>我们平常写templ

大家好,欢迎来到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函数

 

 

 

我们设置一个小案例,通过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函数

 

 

此时要注意,如果没有设置的元素节点,render函数也会加载

1         <render :tag="'aaaaa'" :data="'123456789'"></render>

render函数

 

 

 

这样做有一个好处,就是如果我们的节点是一个ui元素名称,或者是自定义组件,都会被识别

比如我们引入的是element-ui

1         <render :tag="'el-button'" :data="'我是button'"></render>

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>

render函数

 

 

 

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

render函数

 

 

 还可以用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         }

render函数

 

 

最重要的是第三个参数,第三个参数如果不是数组,则表示渲染内容,否则,如果设置了数组,内部必须是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         }

render函数

 

 

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         }

render函数

 

 

页面中进行了识别和解析

 

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"))

render函数

 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30392.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信