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 this关键字使用分析
Oct 21 Javascript
JavaScript中的比较操作符&gt;、=、
Dec 31 Javascript
jquery实现页面常用的返回顶部效果
Mar 04 Javascript
关于javascript中限定时间内防止按钮重复点击的思路详解
Aug 16 Javascript
js 获取本地文件及目录的方法(推荐)
Nov 10 Javascript
微信小程序canvas写字板效果及实例
Jun 15 Javascript
bootstrap多层模态框滚动条消失的问题
Jul 21 Javascript
详解Vue微信公众号开发踩坑全记录
Aug 21 Javascript
Angular项目从新建、打包到nginx部署全过程记录
Dec 09 Javascript
vue.draggable实现表格拖拽排序效果
Dec 01 Javascript
JavaScrip如果基于url实现图片下载
Jul 03 Javascript
TypeScript魔法堂之枚举的超实用手册
Oct 29 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
destoon文章模块调用企业会员资料的方法
2014/08/22 PHP
4种PHP异步执行的常用方式
2015/12/24 PHP
php封装的单文件(图片)上传类完整实例
2016/10/18 PHP
Symfony2获取web目录绝对路径、相对路径、网址的方法
2016/11/14 PHP
php smtp实现发送邮件功能
2017/06/22 PHP
PHP实现微信提现功能
2018/09/30 PHP
在thinkphp5.0路径中实现去除index.php的方式
2019/10/16 PHP
javascript JSON操作入门实例
2010/04/16 Javascript
在IE和VB中支持png图片透明效果的实现方法(vb源码打包)
2011/04/01 Javascript
jQuery Ajax使用实例
2015/04/16 Javascript
javascript实现点击提交按钮后显示loading的方法
2015/07/03 Javascript
jQuery Easyui Datagrid实现单行的上移下移及保存移动的结果
2016/08/15 Javascript
JS组件系列之使用HTML标签的data属性初始化JS组件
2016/09/14 Javascript
Vue学习笔记进阶篇之函数化组件解析
2017/07/21 Javascript
4个顶级开源JavaScript图表库
2018/09/29 Javascript
vue+elementUI实现表单和图片上传及验证功能示例
2019/05/14 Javascript
如何正确理解vue中的key详解
2019/11/02 Javascript
Python实现对比不同字体中的同一字符的显示效果
2015/04/23 Python
Python OS模块常用函数说明
2015/05/23 Python
Nginx搭建HTTPS服务器和强制使用HTTPS访问的方法
2015/08/16 Python
浅谈dataframe中更改列属性的方法
2018/07/10 Python
ITK 实现多张图像转成单个nii.gz或mha文件案例
2020/07/01 Python
Python利用socket模块开发简单的端口扫描工具的实现
2021/01/27 Python
阿迪达斯芬兰官方网站:adidas芬兰
2017/01/30 全球购物
Groupon比利时官方网站:特卖和网上购物高达-70%
2019/08/09 全球购物
新大陆软件面试题
2016/11/24 面试题
传播学毕业生求职信
2013/10/11 职场文书
幼儿园教师工作制度
2014/01/22 职场文书
领导走群众路线整改措施思想汇报
2014/10/12 职场文书
房屋所有权证明
2014/10/20 职场文书
贷款承诺书
2015/01/20 职场文书
2016三严三实专题教育活动心得体会
2016/01/06 职场文书
PHP对接阿里云虚拟号的实现(号码隐私保护)
2021/04/06 PHP
Java基础——Map集合
2022/04/01 Java/Android
SQL Server中搜索特定的对象
2022/05/25 SQL Server
win10如何开启ahci模式?win10开启ahci模式详细操作教程
2022/07/23 数码科技