最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 关于虚拟dom的一些浅见

    正文概述 掘金(啦啦啦啦啦同志)   2021-03-18   522

    老文章了,从简书迁移过来的。

    什么是虚拟DOM

    已经9102年了,前端er或多或少都接触过一些mvvm库,了解有虚拟DOM这么个东西,可能你还没有深入了解过这个东西,其实很简单,来往下看。

    虚拟DOM简而言之就是,用JS去按照DOM结构来实现的树形结构对象,也可以看做是一个JS对象而已。

    结构思考

    什么样的对象才能比较匹配的上dom结构呢?

    来看一下如下图所示的dom结构

    关于虚拟dom的一些浅见

    上图是比较简单的一个结构,比较理想的是使用如下对象来模拟:

    {
        // 节点类型
        type: 'ul',
        // 节点的属性,包括dom原生属性和自定义属性
        props: {
            class: 'list',
            style: 'color:red;'
        },
        // 子节点数组
        // 子对象结构也是一样,包含了type,props,children,没有子节点的话就是普通文本
        // 子对象拥有子节点时,继续往下扩展就行
        children: [
            {type: 'li',props: {class: 'list'},children: ['利群']},
            {type: 'li',props: {class: 'list'},children: ['玉溪']},
            {type: 'li',props: {class: 'list'},children: ['黄鹤楼']}
        ]
    }
    

    OK,对象结构已经解析完成

    批量创建

    我们需要一个类来帮助我们创建对象

    // 定义一个构造函数来
    class Element {
    	constructor(type, props, children) {
    		this.type = type;
    		this.props = props;
    		this.children = children;
    	}
    }
    
    //批量调用构造函数
    function createElement(type,props,children){
    	return new Element(type,props,children);
    }
    
    let virtualDom = createElement('ul',{class:'list',style:'color:red;'},[
            createElement('li',{class:'item'},['利群']),
            createElement('li',{class:'item'},['玉溪']),
            createElement('li',{class:'item'},['黄鹤楼']),
        ]);
    
    // 对象形势的结构展示
    console.log(virtualDom);
    

    OK,查看打印出来的对象是这样的 关于虚拟dom的一些浅见

    将对象变现

    对象有了,那么就该生成dom了

    // 把虚拟对象转成dom对象
    function render(domObj) {
        // 根据元素类型来创建dom
        let el = document.createElement(domObj.type);
    
        // 遍历props对象,然后给创建的元素el设置属性
        for (let key in domObj.props) {
            // 设置属性的方法
            setAttr(el, key, domObj.props[key]);
        }
    
        // 遍历子节点数组
        domObj.children.forEach(child = >{
            // 需要注意的是:如果child是虚拟dom,就继续递归渲染
            if (child instanceof Element) {
                child = render(child);
            } else {
                // 只是普通的文本内容
                child = document.createTextNode(child);
            }
            // 把子节点添加到父节点中
            el.appendChild(child);
        });
    
        return el;
    }
    
    // 上面用到的设置属性
    function setAttr(node, key, value) {
        // 需要判断key是什么
        switch (key) {
        case 'value':
            // 属性是value就要看标签类型了,input和textarea的value就需要做区别
            if (node.tagName.toLowerCase() === 'input' || node.tagName.toLowerCase() == 'textarea') {
                node.value = value;
            } else {
                node.setAttribute(key, value);
            }
            break;
        case 'style':
            node.style.cssText = value;
            break;
        default:
            node.setAttribute(key, value);
            break;
        }
    }
    
    // 将元素插入页面
    function renderDom(el, target) {
        target.appendChild(el);
    }
    
    // 定义一个构造函数来
    class Element {
        constructor(type, props, children) {
            this.type = type;
            this.props = props;
            this.children = children;
        }
    }
    
    //批量调用构造函数
    function createElement(type,props,children){
        return new Element(type,props,children);
    }
    
    // 调用之前的createElement方法
    let virtualDom = createElement('ul',{class:'list',style:'color:red;'},[
            createElement('li',{class:'item'},['利群']),
            createElement('li',{class:'item'},['玉溪']),
            createElement('li',{class:'item'},['黄鹤楼']),
        ]);
    
    // 对象形势的结构展示
    console.log(virtualDom);
    			
    // 渲染dom
    let el = render(virtualDom); // 得到dom元素
    console.log(el);
    renderDom(el,document.querySelector('body'));
    

    OK,结果如下:

    关于虚拟dom的一些浅见

    我们为什么要模拟dom

    这里不讲实现逻辑,只讲下这个虚拟dom的优点(我目前知道的)。

    1. 虚拟dom对象发生改变时,方便我们做新旧对象的对比分析,比如说只是修改了class属性,那么我们只需要修改对应的点,而不用全部覆盖式的更新视图
    2. 如果频繁的去获取操作dom浏览器也会频繁的去更新视图,那么也会有一定的性能损失,造成性能的浪费,现在我们可以收集到修改操作之后,再一次性的把视图修改了,也免得引起浏览器过多的重绘和重排
    3. 对于多端操作的更方便适配。浏览器中我们把虚拟dom生成html,但是到了app和桌面软件中,就不能够使用了,如果想用js写更多端的代码,有了虚拟dom,我们只需要拿这些dom去生成其他的布局结构就行了,如果不涉及到获取和操作宿主环境的api,内部逻辑甚至都可以基本保持不变,这就很强大了

    起源地下载网 » 关于虚拟dom的一些浅见

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元