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双向绑定机制的原理和代码实现的更多相关文章

  1. Vue.js双向绑定的实现原理和模板引擎实现原理(##########################################)

    Vue.js双向绑定的实现原理 解析 神奇的 Object.defineProperty 这个方法了不起啊..vue.js和avalon.js 都是通过它实现双向绑定的..而且Object.obser ...

  2. C#使用Xamarin开发可移植移动应用(3.进阶篇MVVM双向绑定和命令绑定)附源码

    前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.. 嗯..前面 ...

  3. C#使用Xamarin开发可移植移动应用(4.进阶篇MVVM双向绑定和命令绑定)附源码

    前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.. 嗯..前面 ...

  4. 梳理vue双向绑定的实现原理

    Vue 采用数据劫持结合发布者-订阅者模式的方式来实现数据的响应式,通过Object.defineProperty来劫持数据的setter,getter,在数据变动时发布消息给订阅者,订阅者收到消息后 ...

  5. Vue双向绑定的实现原理系列(四):补充指令解析器compile

    补充指令解析器compile github源码 补充下HTML节点类型的知识: 元素节点 Node.ELEMENT_NODE(1) 属性节点 Node.ATTRIBUTE_NODE(2) 文本节点 N ...

  6. Vue双向绑定的实现原理系列(一):Object.defineproperty

    了解Object.defineProperty() github源码 Object.defineProperty()方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象. ...

  7. 【.NET6+WPF】WPF使用prism框架+Unity IOC容器实现MVVM双向绑定和依赖注入

    前言:在C/S架构上,WPF无疑已经是"桌面一霸"了.在.NET生态环境中,很多小伙伴还在使用Winform开发C/S架构的桌面应用.但是WPF也有很多年的历史了,并且基于MVVM ...

  8. 【Maui正式版】创建可跨平台的Maui程序,以及有关依赖注入、MVVM双向绑定的实现和演示

    前言:Maui终于在昨天(2022年8月9日)推送出来了.今儿就迫不及待来把玩一下先. A.我本地已有VS2022,不过版本比较老,此处选择更新.工具 -> 获取功能和更新里面,可以获取到新版本 ...

  9. Vue双向绑定的实现原理系列(三):监听器Observer和订阅者Watcher

    监听器Observer和订阅者Watcher 实现简单版Vue的过程,主要实现{{}}.v-model和事件指令的功能 主要分为三个部分 github源码 1.数据监听器Observer,能够对数据对 ...

随机推荐

  1. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 按钮:用于要弹出信息的按钮

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  2. Ajax接收Json数据,调用template模板循环渲染页面的方法

    一. 后台接口吐出JSON数据 后台php接口中,需要写三个部分: 1.1 开头header规定数据格式: header("content-type:application/json;cha ...

  3. jmeter学习笔记---循环控制器计数器函数助手

    循环控制器与计数器,以及函数助手需要配合使用,实现循环 循环控制器的“循环次数”输入最大循环次数的参数 计数器:除输入最大值外,还需要输入“引用名称”,供后续请求使用 请求中,如果需要实现循环,需要借 ...

  4. 提升Essay写作质量,可从这三个层次入手

    “有针对性”读书对写Essay的产生的帮助是非常大的.由浅显的直接成效,到深度的铺垫积累,阅读一共可分为三个层次: 1读Essay: 2读与写作题材相关的材料: 3多样化阅读. 第一层次:读Essay ...

  5. python-python基础2

    本章内容: 1.列表.元组 2.字典 3.集合 4.文件操作 5.字符编码与转码 一.列表.元组操作 列表是我们最以后最常用的数据类型之一,通过列表可以对数据实现最方便的存储.修改等操作 names= ...

  6. MySQL 通过SQL语句导出表为文件

    SELECT * //你要导出的字段 FROM `tabel` //表名 INTO OUTFILE "D:\\file.txt" //导出的文件路径和文件名 LINES TERMI ...

  7. PAT (Advanced Level) 1132~1135:1132 模拟 1133模拟(易超时!) 1134图 1135红黑树

    1132 Cut Integer(20 分) 题意:将一个含K(K为偶数)个数字的整数Z割分为A和B两部分,若Z能被A*B整除,则输出Yes,否则输出No. 分析:当A*B为0的时候,不能被Z整除,输 ...

  8. 51nod 1099:任务执行顺序 贪心

    1099 任务执行顺序 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题  收藏  取消关注 有N个任务需要执行,第i个任务计算时占R[i]个空间,而后会释放一部分, ...

  9. git 创建分支并提交代码

    1.查看所有分支 git branch -a 2.查看当前分支 git branch 3.新建一个分支 git branch feature-xx 4.切换到新建分支上面 git checkout f ...

  10. 剑指offer 把字符串转化为整数

    题目描述 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 数值为0或者字符串不是一个合法的数值则返回0 输入描述: 输入一个字符串,包括数字字母符号,可以为空 输出描述: 如果是合法 ...