小小的尝试了下js的数据双向绑定,这里采用原生js复现的方式来理解其原理。
DirtyCheck(代表angular js)
脏数据检测的方式主要通过为每个数据添加一个watcher方法(用于返回最新的数据)、lastData(原有数据)、回调函数,当一定的事件发生时(例如keydown、ajax请求完成等),来触发脏数据检测方法。该方法用来对比每个数据的最新的数据与原有的数据是否一致如果不一致则触发该数据所绑定的回调函数用于同步修改Dom及Data。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title></title> </head>
<body>
<input type="text" id="dom_input" /> <span id="dom_output"></span> <script>
var Scope = function () { this.$$watchers = []; };
Scope.prototype.$watch = function (watchExp, listener) { this.$$watchers.push({ watchExp: watchExp, listener: listener || function () { } }); };
Scope.prototype.$digest = function () { var dirty;
do { dirty = false; for (var i = 0; i < this.$$watchers.length; i++) { var newValue = this.$$watchers[i].watchExp(), oldValue = this.$$watchers[i].last; if (oldValue !== newValue) { this.$$watchers[i].listener(newValue, oldValue); dirty = true; this.$$watchers[i].last = newValue; } } } while (dirty); };
var $scope = new Scope();
$scope.value = '';
document.getElementById('dom_input').onkeyup = function () { $scope.value = document.getElementById('dom_input').value; $scope.$digest(); };
function _watchExp(){ return $scope.value; }
function _listener(newValue, oldValue){ document.getElementById('dom_input').value = $scope.value; document.getElementById('dom_output').innerHTML = $scope.value; }
$scope.$watch(_watchExp,_listener);
function changeValue() { $scope.value = 'hello word'; $scope.$digest(); };
changeValue()
</script> </body>
</html>
|
defineProperty(代表Vue js)
该方式主要通过obj的defineProperty方法为对象创建新的属性并对该属性的set方法进行重构。在该属性的set方法里实现对Dom和Data的同步修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title></title> </head>
<body> <input type="text" id="dom_input" /> <span id="dom_output"></span> <script> var obj = {}; Object.defineProperty(obj, 'changeValue', { set: function (val) { document.getElementById('dom_output').innerHTML = val; document.getElementById('dom_input').value = val; } }); document.getElementById('dom_input').onkeyup = function (e) { obj.changeValue = e.target.value; }; obj.changeValue = "hello word";
</script> </body>
</html>
|
参考&引用
http://www.jianshu.com/p/e8df6e3f6e34
http://blog.csdn.net/dm_vincent/article/details/38705099
https://www.2cto.com/kf/201507/418507.html
http://blog.csdn.net/dm_vincent/article/details/50344395
https://www.cnblogs.com/yuqing-o605/p/6790709.html?utm_source=itdadao&utm_medium=referral
http://imweb.io/topic/56d40adc0848801a4ba198ce
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
https://github.com/WilberTian/Two-way-data-binding