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的仿flash的广告轮播
Nov 05 Javascript
ajax的hide隐藏问题解决方法
Dec 11 Javascript
img onload事件绑定各浏览器均可执行
Dec 19 Javascript
js读写cookie实现一个底部广告浮层效果的两种方法
Dec 29 Javascript
利用jquery操作Radio方法小结
Oct 20 Javascript
JavaScript函数模式详解
Nov 07 Javascript
javascript基本数据类型及类型检测常用方法小结
Dec 14 Javascript
vue实现移动端图片裁剪上传功能
Aug 18 Javascript
详解用Node.js实现Restful风格webservice
Sep 29 Javascript
Vue实现导航栏的显示开关控制
Nov 01 Javascript
antd Form组件方法getFieldsValue获取自定义组件的值操作
Oct 29 Javascript
vue 数据双向绑定的实现方法
Mar 04 Vue.js
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
PHPMailer安装方法及简单实例
2008/11/25 PHP
一个PHP缓存类代码(附详细说明)
2011/06/09 PHP
初品cakephp 入门基础
2012/02/16 PHP
用php和jQuery来实现“顶”和“踩”的投票功能
2016/10/13 PHP
浅谈php fopen下载远程文件的函数
2016/11/18 PHP
Redis构建分布式锁
2017/03/28 PHP
深入解析Laravel5.5中的包自动发现Package Auto Discovery
2017/09/13 PHP
图片上传即时显示缩略图的js代码
2009/05/27 Javascript
为jquery.ui.dialog 增加“自动记住关闭时的位置”的功能
2009/11/24 Javascript
jquery 简单的进度条实现代码
2010/03/11 Javascript
JavaScript中__proto__与prototype的关系深入理解
2012/12/04 Javascript
A标签中通过href和onclick传递的this对象实现思路
2013/04/19 Javascript
JavaScript使用indexOf获得子字符串在字符串中位置的方法
2015/04/06 Javascript
分享五个有用的jquery小技巧
2015/10/08 Javascript
jQuery插件HighCharts绘制的基本折线图效果示例【附demo源码下载】
2017/03/07 Javascript
Vue DevTools调试工具的使用
2017/12/05 Javascript
es6基础学习之解构赋值
2018/12/10 Javascript
jQuery添加新内容的四个常用方法分析【append,prepend,after,before】
2019/03/19 jQuery
JS快速实现简单计算器
2020/04/08 Javascript
Python爬虫包 BeautifulSoup  递归抓取实例详解
2017/01/28 Python
Python实现将一个大文件按段落分隔为多个小文件的简单操作方法
2017/04/17 Python
python多线程实现TCP服务端
2019/09/03 Python
Python使用QQ邮箱发送邮件报错smtplib.SMTPAuthenticationError
2019/12/20 Python
使用jupyter Nodebook查看函数或方法的参数以及使用情况
2020/04/14 Python
python如何爬取动态网站
2020/09/09 Python
基于Python组装jmx并调用JMeter实现压力测试
2020/11/03 Python
使用豆瓣源来安装python中的第三方库方法
2021/01/26 Python
加拿大领先的牛仔零售商:Bluenotes
2018/01/22 全球购物
美国战术品牌:5.11 Tactical
2019/05/01 全球购物
简述进程的启动、终止的方式以及如何进行进程的查看
2014/02/20 面试题
顶岗实习接收函
2014/01/09 职场文书
英文感谢信格式
2015/01/21 职场文书
毕业答辩开场白范文
2015/05/27 职场文书
2015迎新晚会活动总结
2015/07/16 职场文书
SpringBoot整合Minio文件存储
2022/04/03 Java/Android
Python自动化工具之实现Excel转Markdown表格
2022/04/08 Python