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 相关文章推荐
JavaScript 判断用户输入的邮箱及手机格式是否正确
Dec 08 Javascript
js分页工具实例
Jan 28 Javascript
浅谈js中的闭包
Mar 16 Javascript
基于jQuery Tipso插件实现消息提示框特效
Mar 16 Javascript
webix+springmvc session超时跳转登录页面
Oct 30 Javascript
JS中SetTimeout和SetInterval使用初探
Mar 23 Javascript
js Dom实现换肤效果
Oct 21 Javascript
Vue的事件响应式进度条组件实例详解
Feb 04 Javascript
js常见遍历操作小结
Jun 06 Javascript
Vue + Element UI图片上传控件使用详解
Aug 20 Javascript
基于JavaScript实现大文件上传后端代码实例
Aug 18 Javascript
vue iview 隐藏Table组件里的某一列操作
Nov 13 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 iconv 函数转gb2312的bug解决方法
2009/10/11 PHP
PHP使用get_headers函数判断远程文件是否存在的方法
2014/11/28 PHP
PHP生成条形码大揭秘
2015/09/24 PHP
比较完整的微信开发php代码
2016/08/02 PHP
(转载)JavaScript中匿名函数,函数直接量和闭包
2007/05/08 Javascript
javascript replace()正则替换实现代码
2010/02/26 Javascript
jquery struts 验证唯一标识(公用方法)
2013/03/27 Javascript
js的隐含参数(arguments,callee,caller)使用方法
2014/01/28 Javascript
WordPress中利用AJAX异步获取评论用户头像的方法
2016/01/08 Javascript
基于JavaScript实现类似于百度学术高级检索功能
2016/03/02 Javascript
基于jQuery Ajax实现上传文件
2016/03/24 Javascript
微信小程序 地图定位简单实例
2016/10/14 Javascript
jQuery中select与datalist制作下拉菜单时的区别浅析
2016/12/30 Javascript
微信小程序 input表单与redio及下拉列表的使用实例
2017/09/20 Javascript
bootstrap中selectpicker下拉框使用方法实例
2018/03/22 Javascript
关于自定义Egg.js的请求级别日志详解
2018/12/12 Javascript
Vue实现商品详情页的评价列表功能
2019/09/04 Javascript
[01:00:59]VP VS VG Supermajor小组赛胜者组第二轮 BO3第二场 6.2
2018/06/03 DOTA
实例讲解python函数式编程
2014/06/09 Python
Python中optionParser模块的使用方法实例教程
2014/08/29 Python
python编程嵌套函数实例代码
2018/02/11 Python
python3安装pip3(install pip3 for python 3.x)
2018/04/03 Python
Python3 执行系统命令并获取实时回显功能
2019/07/09 Python
Django错误:TypeError at / 'bool' object is not callable解决
2019/08/16 Python
python爬虫实现获取下一页代码
2020/03/13 Python
css3 旋转按钮 使用CSS3创建一个旋转可变色按钮
2012/12/31 HTML / CSS
英国领先的在线高尔夫设备零售商:Golfgeardirect
2020/12/11 全球购物
若通过ObjectOutputStream向一个文件中多次以追加方式写入object,为什么用ObjectInputStream读取这些object时会产生StreamCorruptedException?
2016/10/17 面试题
护理实习生带教计划
2015/01/16 职场文书
市场督导岗位职责
2015/04/10 职场文书
2015年药房工作总结
2015/04/25 职场文书
优秀教师工作总结2015
2015/07/22 职场文书
2015年文秘个人工作总结
2015/10/14 职场文书
Spring Boot 整合 Apache Dubbo的示例代码
2021/07/04 Java/Android
MySQL索引是啥?不懂就问
2021/07/21 MySQL
Python pandas求方差和标准差的方法实例
2021/08/04 Python