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 相关文章推荐
IE7提供XMLHttpRequest对象为兼容
Mar 08 Javascript
ASP.NET jQuery 实例16 通过控件CustomValidator验证RadioButtonList
Feb 03 Javascript
用JS将搜索的关键字高亮显示实现代码
Nov 08 Javascript
javascript字符串替换及字符串分割示例代码
Dec 12 Javascript
JS基于Ajax实现的网页Loading效果代码
Oct 27 Javascript
jQuery+css实现的tab切换标签(兼容各浏览器)
Jan 28 Javascript
JS获取鼠标选中的文字
Aug 10 Javascript
Node.js 的模块知识汇总
Aug 16 Javascript
详解从零搭建 vue2 vue-router2 webpack3 工程
Nov 22 Javascript
vue路由守卫+登录态管理实例分析
May 21 Javascript
JS阻止事件冒泡的方法详解
Aug 26 Javascript
vite+vue3.0+ts+element-plus快速搭建项目的实现
Jun 24 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
为什么那些咖啡爱好者大多看不上连锁咖啡店?
2021/03/06 咖啡文化
PIGCMS 如何关闭聊天机器人
2015/02/12 PHP
php将从数据库中获得的数据转换成json格式并输出的方法
2018/08/21 PHP
PHP全局使用Laravel辅助函数dd
2019/12/26 PHP
Thinkphp 框架扩展之数据库驱动常用方法小结
2020/04/23 PHP
jquery右下角弹出提示框示例代码
2013/10/08 Javascript
在firefox和Chrome下关闭浏览器窗口无效的解决方法
2014/01/16 Javascript
JavaScript中的null和undefined区别介绍
2015/01/01 Javascript
jQuery检查事件是否触发的方法
2015/06/26 Javascript
js实现当复选框选择匿名登录时隐藏登录框效果
2015/08/14 Javascript
jQuery实现的产品自动360度旋转展示特效源码分享
2015/08/21 Javascript
jquery实现简洁文件上传表单样式
2015/11/02 Javascript
jquery插件EasyUI中form表单提交实例分享
2016/01/11 Javascript
基于javascript实现根据身份证号码识别性别和年龄
2016/01/22 Javascript
jQuery 自定义下拉框(DropDown)附源码下载
2016/07/22 Javascript
简单理解vue中实例属性vm.$els
2016/12/01 Javascript
jQuery+ajax的资源回收处理机制分析
2017/01/07 Javascript
Angular 4.x+Ionic3踩坑之Ionic3.x pop反向传值详解
2018/03/13 Javascript
vue开发拖拽进度条滑动组件
2019/09/21 Javascript
小程序如何自主实现拦截器的示例代码
2019/11/04 Javascript
JS实现音乐导航特效
2020/01/06 Javascript
详解vue父子组件状态同步的最佳方式
2020/09/10 Javascript
使用Django Form解决表单数据无法动态刷新的两种方法
2017/07/14 Python
python 实现对文件夹内的文件排序编号
2018/04/12 Python
Python实现购物车程序
2018/04/16 Python
对Python之gzip文件读写的方法详解
2019/02/08 Python
tensorflow dataset.shuffle、dataset.batch、dataset.repeat顺序区别详解
2020/06/03 Python
Spy++的使用方法及下载教程
2021/01/29 Python
Pottery Barn阿联酋:购买家具、家居装饰及更多
2019/12/08 全球购物
在阿尔卑斯山或希腊度过快乐假期:Alpine Elements
2019/12/28 全球购物
用友笔试题目
2016/10/25 面试题
简述进程的启动、终止的方式以及如何进行进程的查看
2013/07/12 面试题
食品安全标语
2014/06/07 职场文书
支部组织生活会方案
2014/06/10 职场文书
学习与创新自我评价
2015/03/09 职场文书
springmvc直接不经过controller访问WEB-INF中的页面问题
2022/02/24 Java/Android