mvvm双向绑定机制的原理和实现代码(推荐)


Posted in Javascript onJune 07, 2016

mvvm框架的双向绑定,即当对象改变时,自动改变相关的dom元素的值,反之,当dom元素改变时,能自动更新对象的值,当然dom元素一般是指可输出的input元素。

1. 首先实现单向绑定,在指定对象的属性值发生改变时触发callback函数。

2. 单向绑定可采用ES5新增的defineProperty实现(或defineProperties),用了ES5注定就不支持IE9以下了,为了防止递归死循环问题,原有属性需要剪切到一个私有属性中保存。

3. 循环调用defineProperty定义闭包时产生作用域的问题,为解决作用域变量对象的值会取到最后一次运行值问题,多定义一层立即调用的闭包函数将值传入。

4. 我们定义getFN和setFN函数用于在属性get和set的时候触发,它的功能是对私有属性__private的读写并触发回调函数通知UI层更新界面。

5.单向绑定实现完成后,实现反向的绑定,即UI层onchange之后触发更新数据,这个相对比较容易,在dom中通过自定义属性bindKey关联model的值变化,监听使用oninput事件,相比onchange的好处是可以实时变化不用等失焦,而且对右键粘贴、菜单粘贴,拖动文字进文本框等方式都可以触发,完全无死角,缺点是只支持IE9以上,但是在IE9以下有等价的onpropertychange可以用还是能兼容的。

6.总结,双向绑定的原理并不复杂,整体代码不超过50行,非常精简,不过还是有一些技术含量,下面是完整的代码,如果不想使用庞大的框架,可以用一下。ie9以下是不支持的,如要支持ie9以下可以使用avalon,它用vbs做了get,set存取器的封装,这点还是比较强大的。

html:

<div id="container">
  <p>
  name:<input type="text" bindkey="userName">
  </p>
  <p>
  age:<input type="text" bindkey="age">
  </p>
<div>

js:

<script type="text/javascript">
  window.Model={
    userName:"windy",
    age:34,
    skill:["javascript","html","css","jquery","node"],
    
  }
  function bindingModel(model,changeCallback){
    var propertiesMap={};
    model.__private={};
    function getFn(name){
      var result=this.__private[name]
      console.log("get value:"+name+"="+ result);
      return result;
    };
    function setFn(name,val){
      if(this.__private[name]!=val){
        console.log("set value:"+name+"="+val);
       
        this.__private[name]=val;

        if(changeCallback){
          changeCallback(name,val);
        }
      }
    };
    for(elem in model){
      if(model.hasOwnProperty(elem) && elem!="__private" && typeof(model[elem])!="function"){
        (function(propName,propValue){
          model.__private[propName]=propValue;// init value
          propertiesMap[propName]={
            get:function(){ return getFn.call(this,propName)},
            set:function(v){ return setFn.call(this,propName,v)},
            //value:model[elem],
            //writable: true,
            enumerable: true,
            configurable: true
          }
        })(elem,model[elem]);
      }
    }
    Object.defineProperties(model,propertiesMap)
    
  }
  function bindingBoth(model,dom){
    dom.find("[bindkey]").each(function(item){
      var key=$(this).attr("bindkey");
      $(this).val(model[key]);
      $(this).bind("input",function(){
        model[key]=$(this).val();
      })
    });
    bindingModel(model,function(name,val){
      var el=dom.find("[bindkey="+name+"]");
      if(el.val()!=val){
        el.val(val);
      }
      
    });
  }
  bindingBoth(window.Model,$("#container"))
  </script>

以上这篇mvvm双向绑定机制的原理和实现代码(推荐)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
不同浏览器对回车提交表单的处理办法
Feb 13 Javascript
jquery学习笔记 用jquery实现无刷新登录
Aug 08 Javascript
jquery基础教程之数组使用详解
Mar 10 Javascript
谈谈JSON对象和字符串之间的相互转换JSON.stringify(obj)和JSON.parse(string)
Oct 01 Javascript
WebSocket+node.js创建即时通信的Web聊天服务器
Aug 08 Javascript
Vue.js系列之vue-router(上)(3)
Jan 03 Javascript
js/jquery控制页面动态加载数据 滑动滚动条自动加载事件的方法
Feb 08 Javascript
Node.js中的require.resolve方法使用简介
Apr 23 Javascript
将input框中输入内容显示在相应的div中【三种方法可选】
May 08 Javascript
JavaScript实现图片本地预览功能【不用上传至服务器】
Sep 20 Javascript
vue中,在本地缓存中读写数据的方法
Sep 21 Javascript
基于Vue的侧边目录组件的实现
Feb 05 Javascript
jQuery原理系列-常用Dom操作详解
Jun 07 #Javascript
浅析BootStrap栅格系统
Jun 07 #Javascript
浅谈jQuery 选择器和dom操作
Jun 07 #Javascript
BootStrap.css 在手机端滑动时右侧出现空白的原因及解决办法
Jun 07 #Javascript
DOM操作和jQuery实现选项移动操作的简单实例
Jun 07 #Javascript
Knockoutjs 学习系列(二)花式捆绑
Jun 07 #Javascript
Knockoutjs 学习系列(一)ko初体验
Jun 07 #Javascript
You might like
PHP类的静态(static)方法和静态(static)变量使用介绍
2012/02/19 PHP
php中json_encode处理gbk与gb2312中文乱码问题的解决方法
2014/07/10 PHP
PHPUnit安装及使用示例
2014/10/29 PHP
ThinkPHP中I(),U(),$this-&gt;post()等函数用法
2014/11/22 PHP
百度地图经纬度转换到腾讯地图/Google 对应的经纬度
2015/08/28 PHP
利用php的ob缓存机制实现页面静态化方法
2017/07/09 PHP
yii2.0框架使用 beforeAction 防非法登陆的方法分析
2019/09/11 PHP
用window.location.href实现刷新另个框架页面
2007/03/07 Javascript
jquery 图片预加载 自动等比例缩放插件
2008/12/25 Javascript
jQuery的三种$()
2009/12/30 Javascript
JavaScript中for循环的使用详解
2015/06/03 Javascript
js实现的黑背景灰色二级导航菜单效果代码
2015/08/24 Javascript
详解JavaScript的AngularJS框架中的表达式与指令
2016/03/05 Javascript
Node.js读写文件之批量替换图片的实现方法
2016/09/07 Javascript
AngularJS 模块化详解及实例代码
2016/09/14 Javascript
js实现图片加载淡入淡出效果
2017/04/07 Javascript
angularjs实现时间轴效果的示例代码
2017/11/29 Javascript
JS脚本实现网页自动秒杀点击
2018/01/11 Javascript
nodejs取得当前执行路径的方法
2018/05/13 NodeJs
浅谈express.js框架中间件(middleware)
2019/04/07 Javascript
vue-cli3 热更新配置操作
2020/09/18 Javascript
JavaScript中Object、map、weakmap的区别分析
2020/12/15 Javascript
[01:02:09]Liquid vs TNC 2019国际邀请赛淘汰赛 胜者组 BO3 第二场 8.21
2020/07/19 DOTA
matplotlib简介,安装和简单实例代码
2017/12/26 Python
详解django中url路由配置及渲染方式
2019/02/25 Python
python redis连接 有序集合去重的代码
2019/08/04 Python
猎人靴英国官网:Hunter Boots
2017/02/02 全球购物
海蓝之谜(LA MER)澳大利亚官方商城:全球高端奢华护肤品牌
2017/10/27 全球购物
法国票务网站:Ticketmaster法国
2018/07/09 全球购物
艺术学院毕业生自我评价
2014/03/02 职场文书
小区文明倡议书
2014/05/16 职场文书
2014年人事专员工作总结
2014/11/19 职场文书
2015年国庆晚会主持词
2015/07/01 职场文书
教务处干事工作总结
2015/08/14 职场文书
商业计划书之服装
2019/09/09 职场文书
导游词之南京中山陵
2019/11/27 职场文书