1.1 vue3.js虚拟DOM与渲染器 密码保护

1.虚拟DOM

  Vue3纯运行时:假设我们设计一个框架,提供了Render函数,用户可以为该函数提供树形结构数据对象,然后Render会将该对象递归的渲染成DOM元素。

复制代码
const obj={
    tag:'div',
    children:[
        {tag:'span',children:'hello world'}
    ]
}
复制代码

  每个对象都有两个属性,tag代表标签名,children既可以是数组(代表子节点),也可以是一段文本(代表文本子节点)。接着我们来实现Render函数:

复制代码
function Render(obj,root){
    const el=document.createElement(obj.tag);
    if(typeof obj.children==='string'){
        const text=document.createTextNode(obj.children);
        el.appendChild(text)
    }else if(obj.children){
        //递归地调用Render函数
        obj.children.forEach((child)=>Render(child,el))
    }
    root.appendChild(el)
}
复制代码

  有了这两个函数,用户就可以这样使用:

Render(obj,document.body)

运行浏览器,就能输出'hello world'。以上内容就是虚拟DOM的方式。通过创建虚拟的DOM来提升性能和可维护性。

  除此之外,还可以添加props属性标签,用来处理事件,例如:

复制代码
const obj={
    tag:'div',
    props:{
        onClick:handler
    },
    children:[
        {tag:'span',children:'hello world'}
    ]
}
复制代码

对应到Vue.js模板就是:

<div @click=""handler><span></span></div>

2.渲染器

  渲染器的存在就是为了把虚拟DOM编程真实的DOM并渲染到浏览器页面中。例如这段虚拟DOM:

复制代码
const vnode={
    tag:'div',
    props:{
        onClick:()=>alert('hello world')
    },
    children:'click me'
}
复制代码

我们需要编写一个渲染器,把上面这段虚拟DOM渲染为真实的DOM:

复制代码
function render(vnode,container){
    const el=document.createElement(vnode.tag);
    //遍历vnode.props,将属性事件添加到DOM元素
    for(const key in vnode.props){
        if(/^on/.test(key)){
            //如果key以on开头,说明它是事件
            el.addEventListener(
                key.substr(2).toLowerCase(),//事件的click方法
                vnode.props[key]//事件函数
            )
        }
    }
    if(typeof vnode.children==='string'){
        const text=document.createTextNode(vnode.children);
        el.appendChild(text)
    }else if(Array.isArray(vnode.children)){
        //递归地调用Render函数
        vnode.children.forEach((child)=>render(child,el))
    }
    container.appendChild(el)
}
复制代码
  • vnode:虚拟DOM对象
  • container:真实的DOM元素,最为挂在点,渲染器会把DOM渲染到该挂在点下

  接下来调用render函数:

render(vnode,document.body)

在浏览器运行代码,会渲染出‘click me’文本,点击文本,会弹出‘hello world’。

  如果我们做一个小小的改动:

复制代码
const vnode={
    tag:'div',
    props:{
        onClick:()=>alert('hello world')
    },
    children:'click again'//click me改为click again
}
复制代码

对于渲染器来说,它需要精准地找到对象变更点并只更新变更地内容对于这个问题,在后面还会讲到。

posted @ 2022-08-19 13:51  FRwind  阅读(84)  评论(0)    收藏  举报