Vue-數據綁定原理
阿新 • • 發佈:2019-01-03
head 根據 rip 使用 產生 view epg eve 2.4
VueJS 使用 ES5 提供的 Object.defineProperty() 方法實現數據綁定。
感覺實現時主要是在defineProperty的set和get上做了很多文章,在get中確定了data和view的依賴關系,這樣在data改調用set時就可以根據依賴修改view。
Object.defineProperty() - JavaScript | MDN
確定data和view控件(watcher)的依賴關系(dep):get
<!DOCTYPE html> <html lang="en"> <head> <title>Document</title> <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.js"></script> </head> <body> 輸入值:<input id="val" type="text"><br> 文本值:<span id="text"></span><br> <script> var data = {}; var input = ‘default‘; var dep = []; var watcher = null; // 對data的input進行綁定 Object.defineProperty(data, ‘input‘, { // 獲取obj.input時調用,獲取到的obj.input的值為get函數return的值 get: function(){ // 如果有watcher就添加到dep中(與data的input綁定) if (watcher) { dep.push(watcher); } return input; } }); // 找到view中與data.input綁定的控件進行綁定 // 第一個觀察者 watcher = {jq: $(‘#val‘), type: ‘val‘}; watcher.jq.val(data.input); watcher.jq.keyup(function(){ data.input = $(this).val(); }); watcher = null; // 第二個觀察者 watcher = {jq: $(‘#text‘), type: ‘text‘}; watcher.jq.text(data.input); watcher = null; console.log(dep); /* //用jQuery實現: var data = {}; var input = ‘default‘; var dep = []; var watcher = null; // 第一個觀察者 watcher = {jq: $(‘#val‘), type: ‘val‘}; dep.push(watcher); watcher.jq.val(input); watcher.jq.keyup(function(){ data.input = $(this).val(); }); // 第二個觀察者 watcher = {jq: $(‘#text‘), type: ‘text‘}; dep.push(watcher); watcher.jq.text(input); console.log(dep); */ </script> </body> </html>
監聽data的改變,更新依賴於(depend on)data的view控件(watcher):set
<!DOCTYPE html> <html lang="en"> <head> <title>Document</title> <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.js"></script> </head> <body> 輸入值:<input id="val" type="text"><br> 文本值:<span id="text"></span><br> <button id="get">假設從後臺請求數據了</button> <script> var data = {}; var input = ‘default‘; var dep = []; var watcher = null; // 對data的input進行綁定 Object.defineProperty(data, ‘input‘, { // 獲取obj.input時調用,獲取到的obj.input的值為get函數return的值 get: function(){ // 如果有watcher就添加到dep中(與data的input綁定) if (watcher) { dep.push(watcher); } return input; }, /* 對obj.input賦值時調用,val是準備賦值的值 獲取obj.input時會調用get,沒有get會返回undefined (如果只想obj的input《本身》賦值可以設置writable: true,value: 默認值, 但這時再設置get和set就會產生異常) */ set: function(val){ if (val != input) { input = val; $(dep).each(function(){ if (this.type = ‘val‘) { this.jq.val(input); } if (this.type = ‘text‘) { this.jq.text(input); } }); } } }); // 找到view中與data.input綁定的控件進行綁定 // 第一個觀察者 watcher = {jq: $(‘#val‘), type: ‘val‘}; watcher.jq.val(data.input); watcher.jq.keyup(function(){ data.input = $(this).val(); }); watcher = null; // 第二個觀察者 watcher = {jq: $(‘#text‘), type: ‘text‘}; watcher.jq.text(data.input); watcher = null; console.log(dep); $(‘#get‘).click(function(){ data.input = ‘後臺的數據‘; }); /* //用jQuery實現: var data = {}; var input = ‘default‘; var dep = []; var watcher = null; // 第一個觀察者 watcher = {jq: $(‘#val‘), type: ‘val‘}; dep.push(watcher); watcher.jq.val(input); watcher.jq.keyup(function(){ var input = $(this).val(); $(dep).each(function(){ if (this.type = ‘val‘) { this.jq.val(input); } if (this.type = ‘text‘) { this.jq.text(input); } }); }); // 第二個觀察者 watcher = {jq: $(‘#text‘), type: ‘text‘}; dep.push(watcher); watcher.jq.text(input); console.log(dep); $(‘#get‘).click(function(){ var input = ‘後臺的數據‘ $(dep).each(function(){ if (this.type = ‘val‘) { this.jq.val(input); } if (this.type = ‘text‘) { this.jq.text(input); } }); }); */ </script> </body> </html>
Vue-數據綁定原理