【原】数据双向绑定和虚拟dom探究

自各个mvvm框架出现和流行以来,他们都实现了两个新的概念及功能:数据双向绑定和虚拟dom。网上对于这两个概念的阐述很多很全面,这里仅对它们的原理和应用场景进行探究和记录,希望更接地气的理解和应用这两个新概念。

1.数据双向绑定

先说说数据双向绑定的应用场景.借之前的文章《从web技术的发展探索mvvm模式的形成》来看,前端数据渲染从前端模板技术发展到viewModel以后,拿到数据后往页面的渲染,不再需要我们始终按照流程来操作dom,更好的方式是搭建好数据和视图的关系,通过数据去驱动视图的渲染。

当然用户对视图的操作也驱动了数据的变更。viewModel绑定了来自视图方面和来自数据方面的两方面驱动,这就可以理解为数据双向绑定的核心。先来看一个实时显示数据的autoComplete效果:

 
  //通过触发input的change事件来发出jsonp请求,请求数据并发送回调函数名
  function ck(){
    var script = document.createElement("script");
    var word = oInput.value;
    var src = 'http://suggestion.baidu.com/su?wd='+word+'&cb=succ';
    script.setAttribute('src',src);
    script.id = "aa";
    if(document.getElementById("aa")){
     document.getElementsByTagName('body')[0].removeChild(document.getElementById("aa")); 
    }
    document.getElementsByTagName('body')[0].appendChild(script); 
  }
  if(ie){
    oInput.onpropertychange = function(){  //IE
        ck()
        }
  }
  else{
    oInput.addEventListener("input",ck,false)
  }
//在jsonp的回调函数中执行后续视图操作
function succ(json){ ///... }

运行查看-----模拟百度搜索框提示

通过input的input事件,监听value值的变化,然后驱动数据,数据返回后通过jsonp的回调函数执行视图渲染。此时数据是通过input事件单方面驱动的。同样的我们可以双向绑定的方式实现类似效果。通过Object.defineProperty方法的存取器setter和getter,来监听某个对象属性的变更,并触发变更后的回调函数,如下:

<input type="text" id="input1">
<p id="p1"></p>
function viewRender(val){
   document.getElementById('p1').innerHTML = val;
}
function viewModel(){
    var list = '';
    Object.defineProperty(this,"list",{
        get:function(){return list;},
        set:function(val){
            list = val;
            oInput.value = val;  //修改视图
            viewRender(val);     //回调
        }
    });
}
var ie = !-[1,];
var oInput = document.getElementById('input1');
var oData = new viewModel();
if(ie){
    oInput.onpropertychange = function(){  //IE
       oData.list = oInput.value;
    }
}
else{
    oInput.addEventListener("input",function(){
       oData.list = oInput.value;
    },false)
}

-----实现数据双向绑定,从数据方向驱动


2.虚拟dom

前端请求到数据然后渲染或更新页面视图时,需要操作大量的dom.以往修改dom的方式,一种是appendChild,一种是innerHTML,它们相比性能相差不大,innerHTML略胜一些.修改时都对dom做了的大量操作,引发浏览器的重构和重绘,非常影响页面性能。

虚拟dom方案是在页面渲染dom树时,先在内存中模拟一个dom树,然后比较两颗dom树的不同,再将不同的地方渲染进dom,控制页面重构重绘的范围.这里我们对比下两种方案在渲染dom时,dom树的重构范围。

//将数据oData渲染进下面的视图
var oData = {"o_name":"xiaoming","o_age":19,"o_sex":"男","o_email":"222@qq.com","o_address":"北大街"}
<div id="box">
 <div class="o_tit">个人中心</div>
 <div class="o_name">
    您好:<span>admin</span>
 </div>
 <div class="o_info">
    <p class="o_age">20</p>
    <p class="o_sex">男</p>
    <p class="o_email">111@qq.com</p>
    <p class="o_address">南大街</p>
 </div>
</div>

-----点击测试

当我们点击渲染新数据后,可以发现页面渲染时dom的修改范围很大,有些数据一样的地方和不需要刷新的地方都被重构了,并且重复点击渲染时dom也在重复渲染:


接着我们利用vue来渲染同样的结构:点击测试

此时我们可以清楚的看到,用户中心和性别这两处没有被重构.并且当我们重复点击渲染按钮时也不会重复重构。当我们渲染大量数据,且数据复杂不规律时,虚拟dom更能显示出其优势:

 欢迎转载:转载时请注明本文出处及文章链接

标签:


添加新评论

captcha
请输入验证码