虚拟dom--render函数

     现在时代的开发最求高效率,高应用,高频率快速迭代开发!!!,JavaScript做为大前端的唯一开发语言,在很多的时候原生的js并不能满足热门的开发需求,于是各种高效开发的框架层出不穷,基于最近几年新出的这些框架的底层大多依赖于虚拟dom的快速开发,并不同于以往的jQuer的dom开发,极大地提高了开发人员的开发效率和维护效率
轮子会开固然很好,但是会开久了,就会深纠于如何自己造出轮子!!!
提起轮子那么一定要知道虚拟dom这个轮子到底替我们干了什么,下面一张图解释一下,浏览器解析js的过程在这里插入图片描述     基于这张图我们不难看出我们平常工作的项目的页面原理与结构,其中将html与style结合起来的便是我们的Render Tree也就是渲染树,渲染树将两者结合使用JavaScript进行控制,将项目比作房屋,那么html是屋子的墙体骨骼,style就是屋子的粉饰装修,js就是各种房屋使用功能的控制开关!!!,虚拟dom就是简化我们创建房屋的高效工具在这里插入图片描述
     如果你写过那种php加jq的前后端不分离的老项目,那么你开发的时候,每次的调试一定伴随着大量的dom布局渲染,每次渲染都伴随着大量的内存被占用消耗加载,其中的原理如下图在这里插入图片描述

     计算机就是将我们的代码属性编译成我们所描写的格式,每次代码属性的更改就伴随着大量的重新计算,html的页面加载时从上到下的,js也是如此,每次先行计算你所书写的html的template代码然后计算js方法,最后是你的style属性,style属性也可以放到项目的上级,这个无伤大雅,反正都是要 执行一遍的,计算页面布局,计算js的逻辑和内存占比,计算无效变量的垃圾回收(所以为了不污染全局环境,养成一个良好的行为习惯,避免使用var的命名变量,减少消耗)
言归正传,开发人员为了避免使用大量节点的消耗,于是便使用起render tree的函数,写习惯react的小伙伴对此应该最为习惯!!!在这里插入图片描述
render 函数即渲染函数,它是个函数,它的参数也是个函数——即 createElement,我们重点来说 createElement 参数。
render 函数的返回值(VNode)
VNode(即:虚拟节点),也就是我们要渲染的节点。
render 函数的参数(createElement)
createElement 是 render 函数 的参数,它本身也是个函数,并且有三个参数
createElement 函数的返回值(VNode)
createElement 函数的返回值是 VNode(即:虚拟节点)。
createElement 函数的参数(三个)
一个 HTML 标签字符串,组件选项对象,或者解析上述任何一种的一个 async 异步函数。类型:{String | Object | Function}。必需。
一个包含模板相关属性的数据对象你可以在 template 中使用这些特性。类型:{Object}。可选。
子虚拟节点 (VNodes),由 createElement() 构建而成,也可以使用字符串来生成“文本虚拟节点”。类型:{String | Array}。可选。

import {h,} from "snabbdom";
import './index.less'
const demoDOM = [
    h('h1',
        {
            class: {
                "show-demo-title": true
            }
        },
        "Thanks You"),
    h('div',
        {
            class: {
                "show-demo-img-5": true
            }
        })
]
const content = {
    desc: [
        {
            text: "本次分享主要介绍了浏览器渲染引擎的渲染过程以及虚拟DOM",
            class: { "vnode-text": true }
        },
        {
            text: "通过渲染过程我们可以清晰的了解前端代码是如何转换成图形展示在用户浏览器上。",
            class: { "vnode-text": true }
        },
        {
            text: "虚拟DOM在目前流行的几大框架中都作为核心的一部分使用,可见其性能的高效,虚拟DOM为前端开发提供更爽、更高效的研发模式,同时保持着还不错的性能。",
            class: { "vnode-text": true }
        }
    ]
}


const descList = content.desc.map(element => h("p", { class: element.class }, element.text))
const DOM = [...descList]
export default { demoDOM, DOM }

     这里是一个小的页面dom的布局书写,借用的snabbdom这个强大的dom库!!!,写成一个render函数拿到主视图层进行渲染和控制!

import {
    h,
} from "snabbdom";
import demo1 from "./demo1";
import demo2 from "./demo2";
import demo3 from "./demo3";
import demo4 from "./demo4";
import demo5 from "./demo5";
import "./index.less"

function handleSelect(index, state) {
    let selectDOM = {
        demoDOM: [],
        DOM: [],
    }
    let style = {}
    let showClass = {
        "show-demo-box": true
    }
    if (state) {
        style = {
            opacity: "0",
            transform: "scale(0)",
        }
    } else {
        style = {
            opacity: "1",
            transform: "scale(1)"
        }
    }
    switch (index) {
        case 1:
            selectDOM = demo1
            break
        case 2:
            selectDOM = demo2
            break
        case 3:
            selectDOM = demo3
            break
        case 4:
            selectDOM = demo4
            break
        case 5:
            selectDOM = demo5
            break
        default:
            style = {
                opacity: "0",
                transform: "scale(0)"
            }
            break
    }
    return {
        demoDOM: h('div',
            {
                key: "show-demo-box",
                style: style,
                class: showClass,
            }, selectDOM.demoDOM),
        DOM: selectDOM.DOM
    }
}
export default handleSelect

     在这里我们做视图层的html结构代码,并进行处理

import {
    init,
    classModule,
    propsModule,
    styleModule,
    eventListenersModule,
    h,
} from "snabbdom";
import '@/css/vnode.less'
import demoDOM from "./components"
class Vnode {
    constructor() {
        this.patch = init([
            // Init patch function with chosen modules
            classModule, // makes it easy to toggle classes
            propsModule, // for setting properties on DOM elements
            styleModule, // handles styling on elements with support for animations
            eventListenersModule, // attaches event listeners
        ]);
        this.vnode = null
        this.newVnode = null
        this.vnodeDemo = null
        this.newVnodeDemo = null
        this.data = this.data()
        this.demoDOM = demoDOM
    }
    run() {
        window.addEventListener("DOMContentLoaded", () => {
            this.newVnode = this.list()
            this.vnode = this.patch(document.getElementById("container"), this.view())
            this.newVnodeDemo = this.demoDOM().demoDOM
            this.vnodeDemo = this.patch(document.getElementById("demoContainer"), this.newVnodeDemo)
            this.render()
            this.renderDemo()
        });
    }
    render() {
        this.vnode = this.patch(this.vnode, this.view())
    }
    renderDemo() {
        this.vnodeDemo = this.patch(this.vnodeDemo, this.newVnodeDemo)
    }
    view() {
        return h("div", { class: { "vnode-box": true } }, [
            h("h2", { key: this.data.head, class: { "vnode-title": true }, }, this.data.head),
            h(
                "div", { class: { "vnode-content": true } }, this.newVnode
            ),
        ]);
    }
    select(row) {
        if (row) {
            const DOM = this.demoDOM(row?.rank)
            this.data.head = row.title
            this.data.selected = row.rank
            this.newVnode = this.row(DOM.DOM)
            this.newVnodeDemo = DOM.demoDOM
        } else {
            const DOM = this.demoDOM(this.data.selected, true)
            this.data.head = "目录"
            this.data.selected = 0
            this.newVnode = this.list()
            this.newVnodeDemo = DOM.demoDOM
        }
        this.render()
        this.renderDemo()
    }
    list() {
        const list = this.data.movies.map((movies) => {
            return h("h3",
                {
                    class: { "row": true },
                    on: {
                        click: () => {
                            this.select(movies)
                        }
                    }
                }, movies.title)
        })
        return h("div",
            {
                key: "row-box",
                class: { "row-box": true },
            }, list)
    }
    row(DOM) {
        const backBtn = h("div",
            {
                class: { "button-box": true },
            },
            [h("div",
                {
                    class: { "button": true },
                    on: {
                        click: () => {
                            this.select()
                        }
                    }
                }, '返回目录')])
        return h("div",
            {
                key: "text-box",
                class: { "text-box": true }
            }, [backBtn, h("div",
                {
                    key: "text-show-box",
                    class: { "text-show-box": true }
                }, DOM)])

    }
    data() {
        return {
            selected: 0,
            head: "目录",
            movies: [
                {
                    rank: 1,
                    title: "浏览器解析渲染过程",
                },
                {
                    rank: 2,
                    title: "Render Tree",
                },
                {
                    rank: 3,
                    title: "布局渲染",
                },
                {
                    rank: 4,
                    title: "虚拟DOM",
                },
                {
                    rank: 5,
                    title: "总结",
                },
            ]
        }
    }
}

const domVnode = new Vnode()
domVnode.run()


 <div class="main">
        <div id="container"></div>
        <div class="placeholder"></div>
        <div id="demoContainer"></div>
    </div>

     这是他的主index.html是个很小很小的html结构,于是基于webpack搭建的一个小的demo就这样出现了!
项目demo
百度网盘:https://pan.baidu.com/s/1pioBqCO8TEwAobe57pUs2A
提取码:dae0

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值