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 相关文章推荐
jQuery 名称冲突的解决方法
Apr 08 Javascript
jquery 层次选择器siblings与nextAll的区别介绍
Aug 02 Javascript
编写高效jQuery代码的4个原则和5个技巧
Apr 24 Javascript
jQuery菜单插件superfish使用指南
Apr 21 Javascript
jQuery入门之层次选择器实例简析
Dec 11 Javascript
JavaScript兼容浏览器FF/IE技巧
Aug 14 Javascript
jQuery 出现Cannot read property ‘msie’ of undefined错误的解决方法
Nov 23 Javascript
Angular中的$watch、$watchGroup、$watchCollection
Jun 25 Javascript
vue loadmore 组件滑动加载更多源码解析
Jul 19 Javascript
微信小程序前端自定义分享的实现方法
Jun 13 Javascript
详解Node.js使用token进行认证的简单示例
May 25 Javascript
vue实现多个echarts根据屏幕大小变化而变化实例
Jul 19 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页面缓存ob系列函数介绍
2012/10/18 PHP
CodeIgniter框架URL路由总结
2014/09/03 PHP
ThinkPHP框架整合微信支付之Native 扫码支付模式二图文详解
2019/04/09 PHP
JS高级调试技巧:捕获和分析 JavaScript Error详解
2014/03/16 Javascript
JQuery中DOM实现事件移除的方法
2015/06/13 Javascript
javascript特殊日历控件分享
2016/03/07 Javascript
怎么限制input的text里输入的值只能是数字(正则、js)
2016/05/16 Javascript
bootstrapValidator自定验证方法写法
2016/12/01 Javascript
Vue filters过滤器的使用方法
2017/07/14 Javascript
JavaScript 高性能数组去重的方法
2018/09/20 Javascript
解决antd 下拉框 input [defaultValue] 的值的问题
2020/10/31 Javascript
Taro小程序自定义顶部导航栏功能的实现
2020/12/17 Javascript
[02:30]DOTA2放量测试专访海涛:呼吁保护新手玩家
2013/08/26 DOTA
[40:03]DOTA2上海特级锦标赛主赛事日 - 1 败者组第一轮#1EHOME VS Archon
2016/03/02 DOTA
[03:54]Ehome出征西雅图 回顾2016国际邀请赛晋级之路
2016/08/02 DOTA
[00:31]DOTA2荣耀之路7:Miracle-空血无敌斩
2018/05/31 DOTA
python动态监控日志内容的示例
2014/02/16 Python
Python转换HTML到Text纯文本的方法
2015/01/15 Python
PyQt5利用QPainter绘制各种图形的实例
2017/10/19 Python
pandas 选择某几列的方法
2018/07/03 Python
Django-Rest-Framework 权限管理源码浅析(小结)
2018/11/12 Python
利用python提取wav文件的mfcc方法
2019/01/09 Python
python远程连接MySQL数据库
2019/04/19 Python
Python中的sys.stdout.write实现打印刷新功能
2020/02/21 Python
HTML5 File接口在web页面上使用文件下载
2017/02/27 HTML / CSS
美国便宜的横幅和标志印刷在线:Best of Signs
2019/05/29 全球购物
《花瓣飘香》教学反思
2014/04/15 职场文书
市级绿色学校申报材料
2014/08/25 职场文书
村委会贫困证明范本
2014/09/17 职场文书
婚前保证书范文
2015/02/28 职场文书
生日祝酒词大全
2015/08/10 职场文书
初中数学教学随笔
2015/08/15 职场文书
学校标语口号大全
2015/12/26 职场文书
最新农村养殖致富:资金投入较低的创业项目有哪些?
2019/09/26 职场文书
MySQL 存储过程的优缺点分析
2021/05/20 MySQL
Vue3中toRef与toRefs的区别
2022/03/24 Vue.js