vue入门:(底层渲染实现render函数、实例生命周期)

  • vue实例渲染的底层实现
  • vue实例生命周期

一、vue实例渲染的底层实现

1.1实例挂载

在vue中实例挂载有两种方法:第一种在实例化vue时以el属性实现,第二种是通过vue.$mount()方法实现挂载。不管是哪种挂载都不影响vue实例化组件的执行流程和模式,只是通过vue.$mount()方法实现挂载可以更灵活的实现组件复用和挂载。

1 var vm = new Vue({
2     el:‘挂载元素id‘,//实例化el属性实现挂载
3     ...
4 })
5 var vm1 = new Vue({...});
6 vm1.mount(‘挂载元素id‘);//vue.mount()方法实现挂载
7 //参数模型:# + id

1.2构建DOM抽象语法树与template

在vue实例化中有一个非常关键的操作就是构建DOM抽象语法树,基于抽象语法树生成虚拟节点,然后再将数据渲染到虚拟节点上,再将完成数据渲染的节点添加到document中刷新页面,呈现页面效果。构建抽象语法树有三种方式:1.基于绑定的实例化属性el和$mount()方法构建;2.基于实例化属性template添加的模板构建;3.基于ready()的参数构建。

这三种构建方式的优先级:render() > template > el

本质上的el与template与render()函数的参数都是一个原理,通过el就是将el指向的元素的DOM模型的outerHTML属性值拿到,outerHTML属性值与template的形式完全一样就是html文本的字符串形式;然后将这个字符串形式的html文本转换成js对象模型,render()函数中使用的就直接是js对象模型,接着通过js对象模型所表达的html结构转换成AST(抽象语法树)用于构建虚拟节点VNode;render()函数再在这个虚拟节点上渲染数据,完成数据渲染后就添加到html文档中渲染到页面。

通过元素在window上的id指向获取到id匹配的元素节点对象的outerHTML属性值:

1 <div id="app">我是一个div</div>
2 <script>
3     console.log(app.outerHTML);//"<div id="app">我是一个div</div>"
4 </script>

通过vue对象实例化属性template构建vue实例:

1 <div id="app">我是一个div</div>
2 <script>
3     var vm = new Vue({
4         el:"#app",
5         template:`<div>我是template模板构建的节点</div>`
6     })
7 </script>

通过vue实例化将实例化对象属性template的模板替代app指向的原节点,实质上是在vue实例构建过程中如果发现有template就不会再去获取挂载节点的结构了。接着再来看看render()方法如何实现vue实例构建:

<div id="app">我是一个div</div>
<script>
    var vm = new Vue({
        el:"#app",
        template:`<div>我是template模板构建的节点</div>`,
        render(createElement){
            return createElement("p");
        }
    })
</script>

通过添加render()方法刷新页面会发现页面变成了空白,也就是说el挂载原节点和template模板构建的节点都没生效,查看浏览器控制台可以看到在原app指向的节点的位置被一个空的p标签替代了。这就是说render()函数的优先级大于template和el,但是要注意的是vue实例化必须是在通过el或者vue.mount()挂载才会去执行render()节点渲染方法,不然一个不挂载的vue实例有何必要渲染呢?

1.3基于JS对象模型的AST抽象语法树构建及虚拟节点渲染:

render(createElement){
    return createElement(ElementName,ElementProperty,ChildNode);
}

这里不深入讨论render的设计实现,也不讨论虚拟节点的具体底层实现原理,也不深入探究render的复杂应用,仅仅对render()函数基于js对象模型构建AST抽象语法树做出解析。

createElement:声明工具函数的名称;

ElementName:设定抽象语法树根节点元素名称;

ElementProperty:设定根节点元素的属性;

ChildNode:设定子节点;

1 render(createElement){
2     return createElement("p",{
3         style:{
4             color:"red",
5             fontSize:‘18px‘
6         },
7         class:[‘classname1‘,‘classname2‘]
8     },"我是由render构建的p标签");
9 }

基于data的构建方式:

 1 <div id="app">我是一个div</div>
 2 <script>
 3     var vm = new Vue({
 4         el:"#app",
 5         template:`<div>我是template模板构建的节点</div>`,
 6         data:{
 7             classname1:true,
 8             classname2:false,
 9             text:‘我时由render构建的p标签‘
10         },
11         render(createElement){
12             return createElement("p",{
13                 style:{
14                     color:"red",
15                     fontSize:‘18px‘
16                 },
17                 class:{//基于数据绑定class
18                     classname1:this.classname1,
19                     classname2:this.classname2
20                 }
21             },this.text);
22         }
23     })
24 </script>

使用createElement工具方法迭代子节点(在前面的子节点都直接使用字符串,就是说明其是文本节点,使用createElement可以创建元素子节点):

 1 <div id="app">我是一个div</div>
 2 <script>
 3     var vm = new Vue({
 4         el:"#app",
 5         template:`<div>我是template模板构建的节点</div>`,
 6         data:{
 7             classname1:true,
 8             classname2:false,
 9             text:‘我时由render构建的p标签‘
10         },
11         render(createElement){
12             return createElement("p",{
13                 style:{
14                     color:"red",
15                     fontSize:‘18px‘
16                 },
17                 class:{//基于数据绑定class
18                     classname1:this.classname1,
19                     classname2:this.classname2
20                 }
21             },[
22                 ‘我是一个文本节点‘,
23                 createElement(‘h1‘,‘我是h1标签‘),
24                 createElement(‘h2‘,{
25                     style:{
26                         color:‘orange‘
27                     }
28                 },‘我是h2标签‘)
29             ]);
30         }
31     })
32 </script>

其实本质上render()函数与页面渲染中的抽象语法树构建是异曲同工,一个是基于js对象参数构建,一个是通过html文档构建;一个是在js中完成一个是在浏览器底层渲染模型中完成。

二、vue实例生命周期与钩子函数

更多的钩子函数相关内容可以参考这篇博客: https://www.jianshu.com/p/3e91a1c42397

带后期有深入的理解后再来做详细的解析。

原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/11141284.html

时间: 2024-07-28 21:19:18

vue入门:(底层渲染实现render函数、实例生命周期)的相关文章

Vue学习笔记进阶篇——Render函数

本文为转载,原文:Vue学习笔记进阶篇--Render函数 基础 Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML.然而在一些场景中,你真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更接近编译器. <h1> <a name="hello-world" href="#hello-world"> Hello world! </a> </h1>

vue实例生命周期详解

每个 Vue 实例在被创建之前都要经过一系列的初始化过程. 例如,实例需要配置数据观测(data observer).编译模版.挂载实例到 DOM ,然后在数据变化时更新 DOM . 在这个过程中,实例也会调用一些 生命周期钩子 ,这就给我们提供了执行自定义逻辑的机会.例如,created 这个钩子在实例被创建之后被调用 var vm = new Vue({ data: { a: 1 }, created: function () { // `this` 指向 vm 实例 console.log

Vue实例生命周期

前面的话 Vue实例在创建时有一系列的初始化步骤,例如建立数据观察,编译模板,创建数据绑定等.在此过程中,我们可以通过一些定义好的生命周期钩子函数来运行业务逻辑.本文将详细介绍Vue实例的生命周期 图示 下图是Vue实例生命周期的图示 解释 接下来,根据提供的生命周期钩子,对Vue实例各个阶段的情况进行详细说明 [beforeCreate] 在实例开始初始化时同步调用.此时数据观测.事件等都尚未初始化 [created] 在实例创建之后调用.此时已完成数据观测.事件方法,但尚未开始DOM编译,即

Vue实例生命周期+vueRoter

Vue实例生命周期 vue生命周期之beforeCreate 实例创建之前除标签外,所有的vue需要的数据,事件都不存在 vue生命周期之created 实例创建之后,data和事件已经被解析到,el还没有找到 vue生命周期之beforeMount 开始找标签,数据还没有被渲染,事件也没有被监听 vue生命周期之mounted 开始渲染数据,开始监听事件 vue生命周期之beforeUpdata 数据已经被修改在虚拟DOM,但没有被渲染到页面上 vue生命周期之updata 开始使用Diff算

【Vue实例生命周期】 -- 2019-08-08 18:01:29

目录 实例创建之前执行--beforeCreate 实例创建之后执行--created 挂载之前执行--beforeMount 挂载之后执行--mounted 数据更新之前执行--beforeUpdate 数据更新之后执行--updated 实例销毁之前执行--beforeDestroy 实例销毁之后执行--destroyed keep-alive组件激活时执行--activated keep-alive组件停用时执行--deactivated 原文: http://106.13.73.98/_

【Vue实例生命周期】 -- 2019-08-09 12:10:28

目录 实例创建之前执行--beforeCreate 实例创建之后执行--created 挂载之前执行--beforeMount 挂载之后执行--mounted 数据更新之前执行--beforeUpdate 数据更新之后执行--updated 实例销毁之前执行--beforeDestroy 实例销毁之后执行--destroyed keep-alive组件激活时执行--activated keep-alive组件停用时执行--deactivated 原文: http://106.13.73.98/_

【Vue实例生命周期】 -- 2019-08-11 18:47:26

目录 实例创建之前执行--beforeCreate 实例创建之后执行--created 挂载之前执行--beforeMount 挂载之后执行--mounted 数据更新之前执行--beforeUpdate 数据更新之后执行--updated 实例销毁之前执行--beforeDestroy 实例销毁之后执行--destroyed keep-alive组件激活时执行--activated keep-alive组件停用时执行--deactivated 原文: http://106.13.73.98/_

【Vue实例生命周期】 &#591699;

目录 实例创建之前执行--beforeCreate 实例创建之后执行--created 挂载之前执行--beforeMount 挂载之后执行--mounted 数据更新之前执行--beforeUpdate 数据更新之后执行--updated 实例销毁之前执行--beforeDestroy 实例销毁之后执行--destroyed keep-alive组件激活时执行--activated keep-alive组件停用时执行--deactivated 原文: http://blog.gqylpy.co

vuebase---4.实例生命周期

1.beforeCreate 2.created 3.beforemounted 在挂载开始之前被调用:相关的 render 函数首次被调用 4.mounted el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子.如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内. 5.beforeUpdate 数据更新时调用,发生在虚拟 DOM 打补丁之前.这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器. 该钩子在服务器端渲