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的jqDnR拖拽溢出的修改
Feb 12 Javascript
TimergliderJS 一个基于jQuery的时间轴插件
Dec 07 Javascript
用js判断输入是否为中文的函数
Mar 10 Javascript
js打开windows上的可执行文件示例
May 27 Javascript
js 中将多个逗号替换为一个逗号的代码
Jun 07 Javascript
jquery 实现两Select 标签项互调示例代码
Sep 25 Javascript
分享使用AngularJS创建应用的5个框架
Dec 05 Javascript
在vue项目中安装使用Mint-UI的方法
Dec 27 Javascript
快速了解vue-cli 3.0 新特性
Feb 28 Javascript
vue.js的computed,filter,get,set的用法及区别详解
Mar 08 Javascript
bootstrap table表格插件之服务器端分页实例代码
Sep 12 Javascript
es6数组的flat(),flatMap()函数用法实例分析
Apr 18 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
十大感人催泪爱情动漫 第一名至今不忍在看第二遍
2020/03/04 日漫
thinkphp3.2中Lite文件替换框架入口文件或应用入口文件的方法
2015/05/21 PHP
php+Memcached实现简单留言板功能示例
2017/02/15 PHP
PHP实现的redis主从数据库状态检测功能示例
2017/07/20 PHP
Apache+PHP+MySQL搭建PHP开发环境图文教程
2020/08/06 PHP
基于PHP实现邮箱验证激活过程详解
2020/10/28 PHP
javascript下利用arguments实现string.format函数
2010/08/24 Javascript
js+xml生成级联下拉框代码
2012/07/24 Javascript
详解Javacript和AngularJS中的Promises
2016/02/09 Javascript
jQuery UI库中dialog对话框功能使用全解析
2016/04/23 Javascript
使用Javascript判断浏览器终端设备(PC、IOS(iphone)、Android)
2017/01/04 Javascript
Boostrap栅格系统与自己额外定义的媒体查询的冲突问题
2017/02/19 Javascript
javascript 使用正则test( )第一次是 true,第二次是false
2017/02/22 Javascript
微信小程序自定义导航隐藏和显示功能
2017/06/13 Javascript
JavaScript适配器模式详解
2017/10/19 Javascript
mint-ui的search组件在键盘显示搜索按钮的实现方法
2017/10/27 Javascript
使用mock.js随机数据和使用express输出json接口的实现方法
2018/01/07 Javascript
webstorm和.vue中es6语法报错的解决方法
2018/05/08 Javascript
浅谈python正则的常用方法 覆盖范围70%以上
2018/03/14 Python
eclipse创建python项目步骤详解
2019/05/10 Python
Django 中自定义 Admin 样式与功能的实现方法
2019/07/04 Python
详解python路径拼接os.path.join()函数的用法
2019/10/09 Python
PyQT5 emit 和 connect的用法详解
2019/12/13 Python
Anaconda3中的Jupyter notebook添加目录插件的实现
2020/05/18 Python
Python图像处理二值化方法实例汇总
2020/07/24 Python
详解matplotlib中pyplot和面向对象两种绘图模式之间的关系
2021/01/22 Python
Nike香港官网:Nike HK
2019/03/23 全球购物
PatPat香港:婴童服饰和亲子全家装在线购物
2020/09/27 全球购物
教师节商场活动方案
2014/02/13 职场文书
初中生评语大全
2014/04/24 职场文书
经典团队口号大全
2014/06/21 职场文书
2014离婚协议书范文两篇
2014/09/15 职场文书
会议主持词通用版
2019/04/02 职场文书
标准版个人借条怎么写?以及什么是借条?
2019/08/28 职场文书
安装配置mysql及Navicat prenium的详细流程
2021/06/10 MySQL
win10双系统怎么删除一个系统?win10电脑有两个系统删除一个的操作方法
2022/07/15 数码科技