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配合css简单实现返回顶部效果
Sep 30 Javascript
js与jquery获取父元素,删除子元素的两种不同方法
Jan 09 Javascript
浅谈 jQuery 事件源码定位问题
Jun 18 Javascript
jQuery使用post方法提交数据实例
Mar 25 Javascript
jQuery插件slicebox实现3D动画图片轮播切换特效
Apr 12 Javascript
JavaScript操作URL的相关内容集锦
Oct 29 Javascript
Atitit.js的键盘按键事件捆绑and事件调度
Apr 01 Javascript
JavaScript仿微博输入框效果(案例分析)
Dec 06 Javascript
Angular客户端请求Rest服务跨域问题的解决方法
Sep 19 Javascript
详解express + mock让前后台并行开发
Jun 06 Javascript
JS事件循环机制event loop宏任务微任务原理解析
Aug 04 Javascript
8个非常实用的Vue自定义指令
Dec 15 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
使用XHGui来测试PHP性能的教程
2015/07/03 PHP
php 时间time与日期date之间的使用详解及区别
2016/11/07 PHP
js 省地市级联选择
2010/02/07 Javascript
JavaScript 放大镜 移动镜片效果代码
2011/05/09 Javascript
你必须知道的Javascript知识点之&quot;深入理解作用域链&quot;的介绍
2013/04/23 Javascript
JavaScript计算字符串中每个字符出现次数的小例子
2013/07/02 Javascript
jsp网页搜索结果中实现选中一行使其高亮
2014/02/17 Javascript
JS+CSS实现带关闭按钮DIV弹出窗口的方法
2015/02/27 Javascript
jQuery事件的绑定、触发、及监听方法简单说明
2016/05/10 Javascript
Node.js与Sails redis组件的使用教程
2017/02/14 Javascript
在JS中如何把毫秒转换成规定的日期时间格式实例
2017/05/11 Javascript
Vue2.0学习之详解Vue 组件及父子组件通信
2017/12/12 Javascript
利用JS实现一个同Excel表现的智能填充算法
2018/08/13 Javascript
Vue使用watch监听一个对象中的属性的实现方法
2019/05/10 Javascript
Webpack设置环境变量的一些误区详解
2019/12/19 Javascript
js实现查询商品案例
2020/07/22 Javascript
python实现数值积分的Simpson方法实例分析
2015/06/05 Python
python使用xslt提取网页数据的方法
2018/02/23 Python
python 实现数组list 添加、修改、删除的方法
2018/04/04 Python
python 删除非空文件夹的实例
2018/04/26 Python
flask session组件的使用示例
2018/12/25 Python
基于python if 判断选择结构的实例详解
2019/05/06 Python
pytorch梯度剪裁方式
2020/02/04 Python
plt.figure()参数使用详解及运行演示
2021/01/08 Python
美国求婚钻戒网站:Super Jeweler
2016/08/27 全球购物
澳大利亚UGG工厂直销:Australian Ugg Boots
2017/10/14 全球购物
麦当劳印度网上订餐:McDelivery
2020/03/16 全球购物
应届毕业生应聘自荐信
2013/12/07 职场文书
计算机专业毕业生求职信分享
2013/12/24 职场文书
个人作风建设剖析材料
2014/10/11 职场文书
党员干部廉洁自律承诺书
2015/04/28 职场文书
爱国影片观后感
2015/06/18 职场文书
《工作是最好的修行》读后感3篇
2019/12/13 职场文书
分析Python list操作为什么会错误
2021/11/17 Python
Javascript中Microtask和Macrotask鲜为人知的知识点
2022/04/02 Javascript
2022新作动画《福星小子》释出宣传影片 加入内田真礼&宫野真守配音演出
2022/04/08 日漫