双向绑定学习 Object.defineProperty
基于熟悉angularJs情况下学习Vue,自己动手造了个类似的双向绑定,带简单的依赖。
代码所在:https://github.com/huanrum/ehuanrum
例子所在:https://files.cnblogs.com/files/ehuanrum/demo-build.rar
可以引用 https://files.cnblogs.com/files/ehuanrum/framework.css
https://files.cnblogs.com/files/ehuanrum/framework.min.css
https://files.cnblogs.com/files/ehuanrum/framework.js
https://files.cnblogs.com/files/ehuanrum/framework.min.js
该框架的调用接口是window.$ehr,它是一个方法,有如下的参数
1.window.$ehr(true)
表示所有的关于双向绑定的标记都会呈现在dom里面,否则就不呈现
2.window.$ehr(method,method)
只要第一个参数是函数就表示这个在Dom加载完执行的方法,第二个存在就回在dom注销的时候执行
3.window.$ehr('name',function)
第一个参数是字符串就表示我要注册(第二个参数存在)或者获取(第二个参数不存在)一个这个名称的功能
如果第一个参数以.结束就表示我们注册的function,否则就表示我们注册的是function的返回值,这个function有两种写法(类似于angularJs)
a.function(name1,name2...){...} 这里的name1,name2都是我们注入的功能的名称,但是这种写法会导致代码不能混淆
b.['name1','name2',function(name1,name2){...}] 这里的name1,name2都是我们注入的功能的名称
框架自己带上了如下的几个功能,框架里面使用只需要注入到参数里面就行,外面使用的时候是window.$ehr('name')
1.value 用于获取某个对象的值或设置值
var xx = {x:1,y:4,foo:{m:12,n:45}},filed = 'foo.m',action = 'x + y + foo.m';
这时我们需要求得filed和action的运行值就可以用value(xx ,field);value(xx ,action);
2.binding 用于把dom与对应的data绑定起来
var template = '<input [value]="name">',data = {name:'demo'};
binding(template,data[,父Dom][,Controller]);
第一个参数可以是一个字符串或者一个Dom元素
需要注意的是第三个参数,Dom元素是父节点,mathod是controller,字符串是会调路由的
返回的是Dom元素组的scope方法返回绑定的数据,update用于更新父Dom元素
3.filter 用于显示数据格式化
添加 filter window.$ehr('filter.language',function(){
return function(value,...){
//自己的处理逻辑
};
});
使用添加的filter
var template = '<input [value]="name | language">',data = {name:'demo'};
binding(template,data[,父Dom][,Controller]);
4.额外提供了functions,里面包含color和event
color 根据传入参数获取颜色,如果无参数就随机
event 作为一个事件处理,可以注册,注销,或发起
关于注册各种功能
1.注册多个页面
所有已router开头的都是会产生菜单的
window.$ehr('router.about',...)
window.$ehr('router.page',...)
window.$ehr('router.page.child',...)
这时我们就注册了三个页面about,page和page.child,第三个是第二个的子菜单
2.注册自己的控件和指令
所有以control开头的都是自定义指令
window.$ehr('control.my.number',...) 使用请看下面
2.main和filter.menu
如果注册了main,它会在Dom加载完成后执行
关于双向绑定
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link href="https://files.cnblogs.com/files/ehuanrum/framework.css" rel="stylesheet"> <script src="https://files.cnblogs.com/files/ehuanrum/framework.js"></script> </head> <body> <script> $ehr(true); $ehr('filter.demo', ['binding', 'functions.color', function (binding, functions_color) { return function (value, type) { return ('<type style="color:' + functions_color() + '">value</type>').replace('type', type || 'span').replace('value', value); }; }]); $ehr('control.demo', ['binding', function (binding) { return function (element, data, field) { binding('<a [innerHTML]="entity.name|demo(entity.type)" [title]="entity.info" [onclick]="open(entity)"></a><del [innerHTML]="entity.name"></del>'.replace(/entity/g, field), data.$extend({}, [field]), element); }; }]); $ehr('control.if', ['value', function (value) { return function (element, data, field) { var parentNode = element.parentNode, nextSibling; this.defineProperty(data, field, function () { if (value(data, field)) { if (!element.parentNode) { element.update(parentNode, nextSibling); } } else if (element.parentNode) { parentNode = element.parentNode; nextSibling = element.nextSibling element.update(); } }); }; }]); </script> <script> $ehr('router.vue', ['binding', function (binding) { var template = [ '<ul>', '<li :innerHTML="item.name"></li>', '<li @click="open(item)">{{item.name}}</li>', '</ul>' ].join(''); return function (name) { binding(template, { open: function (item) { alert(JSON.stringify(item)); }, item: { name: name + '-Name-1', info: 'Name-1' } }); }; }]); $ehr('router.angular2', ['binding', function (binding) { var template = [ '<ul>', '<li [innerHTML]="item.name"></li>', '<li (click)="open(item)">{{item.name}}</li>', '</ul>' ].join(''); return function (name) { binding(template, { open: function (item) { alert(JSON.stringify(item)); }, item: { name: name + '-Name-1', info: 'Name-1' } }); }; }]); $ehr('router.page', ['binding', function (binding) { var template = '<ul><li [item:items] [demo]="item"></li></ul>'; return function (name) { binding(template, { open: function (item) { alert(JSON.stringify(item)); }, items: [ { name: name + '-Name-1', info: 'Name-1' }, { name: name + '-Name-2', info: 'Name-2', type: 'button' } ] }); }; }]); $ehr('router.work', ['binding', function (binding) { var template = '<ul><li [item:items] [demo]="item"></li></ul>'; return function (name) { binding(template, { open: function (item) { alert(JSON.stringify(item)); }, items: [ { name: name + '-Name-1', info: 'Name-1' }, { name: name + '-Name-2', info: 'Name-2', type: 'strong' } ] }); }; }]); $ehr('router.test', ['binding', function (binding) { var template = '<ul><li [item:items] [demo]="item" [hidden]="item.show" [style.fontSize]="item.size + \'px\'"></li></ul>'; return function (name) { binding(template, { open: function (item) { alert(JSON.stringify(item)); }, items: [ { name: name + '-Name-1', info: 'Name-1' }, { name: name + '-Name-2', info: 'Name-2', type: 'strong' } ] }, function (scope) { var handel = setInterval(function () { scope.items.forEach(function (item) { item.show = Math.random() > 0.1; item.size = Math.floor(Math.random()*20) + 12; }); },1000); scope.$destroy(function () { clearInterval(handel); }); }); }; }]); $ehr('router.input', ['binding', 'random',function (binding,random) { var template = '<ul><li [item:items]><input [type]="item.type" [value]="item.value" [title]="item.formatter"></li></ul>'; return function (name) { binding(template, { open: function (item) { alert(JSON.stringify(item)); }, items: 'button,text|[(){4-20}],number|[(0-9)3-10],email|[(){3-7}]@[(a-z){1-4}].[(a-z){2-4}],range,color|#[(0-f)6],date|[1960-2020]-[1-12]-[1-29],reset,!file'.split(',').map(function(type,index){ return { name: name + '-Name-' + index, auto:!/!/.test(type),formatter:type.split('|')[1],type:type.split('|')[0].replace('!','')}; }) }, function (scope) { var handel = setInterval(function () { scope.items.forEach(function (item) { if(!item.auto){return;} var value = Math.floor(Math.random()*100); if(item.formatter){ value = random(item.formatter); } item.value = value; }); },2000); scope.$destroy(function () { clearInterval(handel); }); function complement(num,length){ return (Array(length).join(0) + num).slice(-length); } }); }; }]); </script> </body> </html>

浙公网安备 33010602011771号