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


    • vue实例渲染的底层实现
    • 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>
    View Code

    使用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

     三、vue实例渲染的生命周期与钩子函数详解

            Vue 渲染底层原理之render函数·Vue 实例生命周期与钩子函数  
    ______________________________________________________________________________ |     Init Events & Lisfecyde:初始化创建vue实例需要的相关事件与实例化生命周 |    期需要的函数。 | |____①___beforeCreate():初始化vue实例之前执行的钩子函数。 | |  Init injections & reactivity:初始化实例,将实例参数:el、data、methods等 |  添加到实例对象上,为构建虚拟DOM做好准备。 |
    |____②___created():初始化vue实例之后执行的钩子函数。 | 构 | 建 el、$mount(el):判断实例是通过哪种挂载方法。 | 抽 判断是否采用template模板,还是通过元素的outerHTML属性构建抽象语法 | 象 树。(所以在这之前需要判断是通过哪种方式挂载,如果没有模板就需要基于 | 语 挂载的node结构来构建抽象语法树) | 法 | 树 |____③___beforeMount():渲染页面之前执行的钩子函数。 | | Create vm.$el and replace “el” with it:基于抽象语法树与数据构建虚拟node, | 并将虚拟node渲染到页面,形成HTML文档,如果之前在HTML中包含定义 | 结构的元素(包含自定义元素)会被替换。(渲染页面包含三个步骤:构建虚 | 拟节点、删除原文节点、插入新的文件节点) | |____④___mounted():渲染页面之后执行的钩子函数。 | |________________________________________________________________________ | | |____⑤___beforeUpdate():重新渲染之前触发的钩子函数。 | | | | Mounted(触发重新渲染—数据迭代更新) | | | |____⑥___update():重新渲染之后触发的渲染函数。 | | |
    |_________________________________________________________________________| | | |____⑦___beforeDestroy():实例销毁前触发的钩子函数。 | | Teardown watchers, child components and event listeners:拆卸监 | 视器、子组件和事件侦听器。) | Destroy【销毁实例】 | |____⑧___destroyed():实例销毁后执行的钩子函数。

  • 相关阅读:
    spring 声明式事务的坑 @Transactional 注解
    这样学Linux基本命令,事半功倍
    NIO buffer 缓冲区 API
    Java技术——你真的了解String类的intern()方法吗
    Spring中配置数据源的4种形式
    Java集合框架List,Map,Set等全面介绍
    阿里面试题:关于类中静态,非静态,构造方法的执行顺序
    web.xml加载顺序
    MyBatis 延迟加载,一级缓存,二级缓存设置
    mybatis 调用存储过程
  • 原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/11141284.html
Copyright © 2020-2023  润新知