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中“+=”的应用
Feb 02 Javascript
举例讲解AngularJS中的模块
Jun 17 Javascript
Jquery中使用show()与hide()方法动画显示和隐藏图片
Oct 08 Javascript
javascript动画之磁性吸附效果篇
Dec 09 Javascript
WEB开发之注册页面验证码倒计时代码的实现
Dec 15 Javascript
Vue keep-alive实践总结(推荐)
Aug 31 Javascript
微信小程序使用toast消息对话框提示用户忘记输入用户名或密码功能【附源码下载】
Dec 09 Javascript
Nginx 配置多站点vhost 的方法
Jan 07 Javascript
JavaScript设计模式之调停者模式实例详解
Feb 03 Javascript
Node.js引入UIBootstrap的方法示例
May 11 Javascript
Angular2之二级路由详解
Aug 31 Javascript
layui实现form表单同时提交数据和文件的代码
Oct 25 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中一个有意思的日期逻辑处理
2012/03/25 PHP
PHP连接SQLServer2005的实现方法(附ntwdblib.dll下载)
2012/07/02 PHP
PHP解密Unicode及Escape加密字符串
2015/05/17 PHP
php简单生成随机数的方法
2015/07/30 PHP
jQuery 连续列表实现代码
2009/12/21 Javascript
使用jQuery的将桌面应用程序引入浏览器
2010/11/19 Javascript
javascript 通用loading动画效果实例代码
2014/01/14 Javascript
使用jQuery的attr方法来修改onclick值
2014/07/07 Javascript
JS获取图片lowsrc属性的方法
2015/04/01 Javascript
jQuery打字效果实现方法(附demo源码下载)
2015/12/18 Javascript
Javascript将数字转化成为货币格式字符串
2016/06/22 Javascript
webpack 开发和生产并行设置的方法
2018/11/08 Javascript
修改layui的后台模板的左侧导航栏可以伸缩的方法
2019/09/10 Javascript
利用JS如何获取form表单数据
2019/12/19 Javascript
python如何通过twisted实现数据库异步插入
2018/03/20 Python
对numpy中布尔型数组的处理方法详解
2018/04/17 Python
Python实现爬虫抓取与读写、追加到excel文件操作示例
2018/06/27 Python
Python3 使用cookiejar管理cookie的方法
2018/12/28 Python
Python Cookie 读取和保存方法
2018/12/28 Python
Python 在OpenCV里实现仿射变换—坐标变换效果
2019/08/30 Python
Python爬虫解析网页的4种方式实例及原理解析
2019/12/30 Python
如何在python中执行另一个py文件
2020/04/30 Python
详解python的super()的作用和原理
2020/10/29 Python
用python写PDF转换器的实现
2020/10/29 Python
CSS3中的常用选择器使用示例整理
2016/06/13 HTML / CSS
京东国际站:JOYBUY
2017/11/23 全球购物
软件测试面试题
2015/10/21 面试题
教师岗位职责范本
2013/12/29 职场文书
小学老师寄语大全
2014/04/04 职场文书
酒店开业庆典策划方案
2014/05/28 职场文书
消防安全标语
2014/06/07 职场文书
幼儿园迎国庆65周年活动策划方案
2014/09/16 职场文书
财务工作犯错检讨书
2014/10/07 职场文书
社保转移委托书范本
2014/10/08 职场文书
党的群众路线教育实践活动个人对照检查材料(公安)
2014/11/05 职场文书
2015年中秋寄语
2015/07/31 职场文书