日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用Object.observe 实现数据绑定

發布時間:2023/12/31 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Object.observe 实现数据绑定 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Object.observe API概述

最近,JavaScript的MVC框架在Web開發屆非常盛行。在實現MVC框架的時候,一個非常重要的技術就是數據綁定技術。如果要實現模型與視圖的分離,就必須要使用數據綁定技術。但是,MVC框架的原作者對于數據綁定處理實現得并不如人意,因此,Google公司在ECMAScript中封裝了一個Object.observe API,專用于實現數據綁定處理(目前將其正式使用在V8中)。

Object.observe API可以被稱為一種“可以對任何對象的屬性值修改進行監視的事件處理函數”。

在Firefox瀏覽器中,實現了與之相類似的可以對DOM對象進行觀察的Mutation觀察器。

目前為止,Object.observe API已經被strawman proposal所承認,被正式使用在V8中。自11月末開始,已經可以在Chrome Canary與開發者通道中對其進行啟用。

本文介紹Object.observe API中的基本功能及一些代碼示例。

目前為止,Object.observe API中包括如下所示的四個方法:

  • Object.observe:為對象指定監視時調用的回調函數
  • Object.unobserve:移除監視時調用的回調函數
  • Object.deliverChangeRecords:通過回調函數對對象值進行修改
  • Object.getNotifier:獲取Notifier對象

可以觀察到的屬性操作包括以下幾種:

  • new:添加屬性
  • updated:修改屬性值
  • reconfigured:修改屬性設定
  • deleted:刪除屬性

接下來介紹如何使用Object.observe方法。

目前(2012年12月6日)為止,如果要使用Object.observe API,需要使用Chrome Canary或Chrome Dev Channel(25.0.1337.0 dev-m以上)版本的瀏覽器,同時在chrome://flags/中啟用“啟用實驗性 JavaScript”選項,如下圖所示。

簡單代碼示例

Object.observe方法用于為對象指定監視到屬性修改時調用的回調函數,使用方法如下所示。

Object.observe(obj, callback);

Object.observe方法中使用兩個參數,其中第一個參數值為需要被監視的對象,第二個參數值為監視到屬性修改時調用的回調函數名。可以將各對象的屬性操作時生成的ChangeRecord對象數組設置為回調函數的參數。

ChangeRecord對象擁有type、name、oldValue、object四個屬性,各屬性含義如下所示。

function callback(changes) {changes.forEach(function(change) {console.log(change.type); //對屬性進行了什么操作 new/updated/reconfigured/deltedconsole.log(change.name); //屬性名console.log(change.oldValue); //修改之前的屬性值console.log(change.object); //被監視的對象}); }

使用如下所示的代碼,可以在任何時刻對于對象屬性的上述四種操作(new/updated/reconfigured/delted)進行監視:

var obj = {a: 1};Object.observe(obj, output); //為對象指定監視時調用的回調函數obj.b = 2; //添加屬性obj.a = 2; //修改屬性值Object.defineProperties(obj, {a: { enumerable: false}}); //修改屬性設定delete obj.b; //刪除屬性 function output(change) {//回調函數,可以在此處書寫在頁面上的輸出。} <!DOCTYPE html> <head> <meta charset="UTF-8" /> <title>Object.observer API代碼示例頁面</title> <style> table, td, th { border: 2px #000000 solid; } </style> <script> window.addEventListener('DOMContentLoaded',function() { if (!Object.observe) { alert('您的瀏覽器不支持Object.observe API。請使用Chrome Canary或Chrome Dev Channel(25.0.1337.0 dev-m以上)版本的瀏覽器,并啟用“啟用實驗性 JavaScript”選項。'); return; } var obj = {a: 1}; Object.observe(obj, output); obj.b = 2; //添加屬性 obj.a = 2; //修改屬性值 Object.defineProperties(obj, {a: { enumerable: false}}); //修改屬性設定 delete obj.b; //刪除屬性 function output(changes) { var results = document.getElementById('results'); var table = document.createElement('table'); results.appendChild(table); var caption = document.createElement('caption'); caption.innerText = '監視到的事件列表'; table.appendChild(caption); var thead = document.createElement('thead'); thead.innerHTML = '<tr><th>序號</th><th>操作種類</th><th>屬性名</th><th>修改前的屬性值</th><th>修改后的屬性值</th></tr>'; table.appendChild(thead); changes.forEach(function(change, i) { var tr = document.createElement('tr'); tr.innerHTML = '<td>' + i + '</td><td>' + change.type + '</td><td>' + change.name + '</td><td>' + change.oldValue + '</td><td>' + change.object[change.name] + '</td>'; table.appendChild(tr); }); } }); </script> </head> <body> <div id="event"><div>示例代碼</div> <pre> obj.b = 2; //添加屬性 obj.a = 2; //修改屬性值 Object.defineProperties(obj, {a: { enumerable: false}}); //修改屬性設定 delete obj.b; //刪除屬性 </pre> </div> <div id="results"></div> </body> </html>

運行代碼

頁面運行結果如下圖所示(在Chrome Canary或Chrome Dev Channel(25.0.1337.0 dev-m以上)版本的瀏覽器中)

創建自定義Notify對象

可以監視到的事件并不局限于以上所述的幾種,可以自定義監視事件。

可以使用Notifier對象來自定義針對對象的可訪問屬性(可使用getter方法或setter方法讀取或設置的屬性)被修改時所觸發的事件。這時,我們需要Object.getNotifier()方法獲取被監視對象的Notifier對象,并使用notify方法進行屬性被修改的通知。

在以下這個示例代碼中,為對象自定義time_updated事件及time_read事件并利用這兩個事件監視對象的私有屬性_time的讀取及修改。

var obj2 = {_time: new Date(0)}; var notifier = Object.getNotifier(obj2); //獲取Notifier對象 Object.defineProperties(obj2, { //設置對象的可訪問屬性 _time: {enumerable: false,configrable: false},seen: {set: function(val) {var notifier = Object.getNotifier(this);notifier.notify({type: 'time_updated', //定義time_updated事件name: 'seen',oldValue: this._time});this._time = val;},get: function() {var notifier = Object.getNotifier(this);notifier.notify({type: 'time_read', //定義time_read事件name: 'seen',oldValue: this._time});return this._time;}} }); Object.observe(obj2, output); //為對象指定監視時調用的回調函數 //執行屬性操作 var first_time = obj2.seen; //觸發time_read事件 obj2.seen = new Date(); //觸發time_updated事件 var second_time = obj2.seen; //觸發time_read事件 <!DOCTYPE html> <head> <title>Object.observer API代碼示例頁面</title> <style> table, td, th { border: 2px #000000 solid; } </style> <script> window.addEventListener('DOMContentLoaded',function() { if (!Object.observe) { alert('您的瀏覽器不支持Object.observe API。請使用Chrome Canary或Chrome Dev Channel(25.0.1337.0 dev-m以上)版本的瀏覽器,并啟用“啟用實驗性 JavaScript”選項。'); return; } var obj2 = {_time: new Date(0)}; var notifier = Object.getNotifier(obj2); Object.defineProperties(obj2, { _time: { enumerable: false, configrable: false }, seen: { set: function(val) { var notifier = Object.getNotifier(this); notifier.notify({ type: 'time_updated', //定義time_updated事件 name: 'seen', oldValue: this._time }); this._time = val; }, get: function() { var notifier = Object.getNotifier(this); notifier.notify({ type: 'time_read', //定義time_read事件 name: 'seen', oldValue: this._time }); return this._time; } } }); Object.observe(obj2, output); var seen = document.getElementById('seen'); var first_seen = document.createElement('div'); var first_time = obj2.seen; //觸發time_read事件 first_seen.innerText = 'first_seen:' + first_time; seen.appendChild(first_seen); obj2.seen = new Date(); //觸發time_updated事件 var second_seen = document.createElement('div'); var second_time = obj2.seen; //觸發time_read事件 second_seen.innerText = 'second_seen:' + second_time; seen.appendChild(second_seen); function output(changes) { var results = document.getElementById('results'); var table = document.createElement('table'); results.appendChild(table); var caption = document.createElement('caption'); caption.innerText = '監視到的事件列表'; table.appendChild(caption); var thead = document.createElement('thead'); thead.innerHTML = '<tr><th>序號</th><th>操作種類</th><th>屬性名</th><th>修改前的屬性值</th></tr>'; table.appendChild(thead); changes.forEach(function(change, i) { var tr = document.createElement('tr'); tr.innerHTML = '<td>' + i + '</td><td>' + change.type + '</td><td>' + change.name + '</td><td>' + change.oldValue + '</td>'; table.appendChild(tr); }); } }); </script> </head> <body> <div id="event"><div>示例代碼</div> <pre> var first_time = obj2.seen; //觸發time_read事件 obj2.seen = new Date(); //觸發time_updated事件 var second_time = obj2.seen; //觸發time_read事件 </pre> </div> <div id="seen"></div> <div id="results"></div> </body> </html>

運行代碼

控制回調函數的執行時間

在默認情況下,使用Object.observe API指定的回調函數將在JavaScript腳本代碼執行結束時被調用。因此如果對同一對象的同一屬性執行了多次操作,回調函數中獲取到的各屬性值為最后一個操作結束后的值。將前面這個示例中的代碼稍作修改,對使用Object.observe API進行監視的對象的屬性值連續修改七次(為了避免回調函數的循環調用刪除對time_read事件的監視)。

obj3.seen = new Date(2013, 0, 1, 0, 0, 0); //觸發time_updated事件obj3.seen = new Date(2013, 0, 2, 0, 0, 0); //觸發time_updated事件obj3.seen = new Date(2013, 0, 3, 0, 0, 0); //觸發time_updated事件obj3.seen = new Date(2013, 0, 4, 0, 0, 0); //觸發time_updated事件obj3.seen = new Date(2013, 0, 5, 0, 0, 0); //觸發time_updated事件obj3.seen = new Date(2013, 0, 6, 0, 0, 0); //觸發time_updated事件obj3.seen = new Date(2013, 0, 7, 0, 0, 0); //觸發time_updated事件 <!DOCTYPE html> <head> <title>Object.observer API代碼示例頁面</title> <style> table, td, th { border: 2px #000000 solid; } </style> <script> window.addEventListener('DOMContentLoaded',function() { if (!Object.observe) { alert('您的瀏覽器不支持Object.observe API。請使用Chrome Canary或Chrome Dev Channel(25.0.1337.0 dev-m以上)版本的瀏覽器,并啟用“啟用實驗性 JavaScript”選項。'); return; } var obj3 = {_time: new Date(0)}; var notifier = Object.getNotifier(obj3); Object.defineProperties(obj3, { _time: { enumerable: false, configrable: false }, seen: { set: function(val) { var notifier = Object.getNotifier(this); notifier.notify({ type: 'time_updated', // 時間更新イベントの定義 name: 'seen', oldValue: this._time }); this._time = val; }, get: function() { return this._time; } } }); Object.observe(obj3, output); obj3.seen = new Date(2013, 0, 1, 0, 0, 0); //觸發time_updated事件 obj3.seen = new Date(2013, 0, 2, 0, 0, 0); //觸發time_updated事件 obj3.seen = new Date(2013, 0, 3, 0, 0, 0); //觸發time_updated事件 obj3.seen = new Date(2013, 0, 4, 0, 0, 0); //觸發time_updated事件 obj3.seen = new Date(2013, 0, 5, 0, 0, 0); //觸發time_updated事件 obj3.seen = new Date(2013, 0, 6, 0, 0, 0); //觸發time_updated事件 obj3.seen = new Date(2013, 0, 7, 0, 0, 0); //觸發time_updated事件 function output (changes) { var results = document.getElementById('results'); var table = document.createElement('table'); results.appendChild(table); var caption = document.createElement('caption'); caption.innerText = '監視到的事件列表'; table.appendChild(caption); var thead = document.createElement('thead'); thead.innerHTML = '<tr><th>序號</th><th>操作種類</th><th>屬性名</th><th>修改前的屬性值</th><th>修改后的屬性值</th></tr>'; table.appendChild(thead); changes.forEach(function(change, i) { var tr = document.createElement('tr'); tr.innerHTML = '<td>' + i + '</td><td>' + change.type + '</td><td>' + change.name + '</td><td>' + change.oldValue + '</td><td>' + change.object[change.name] + '</td>'; table.appendChild(tr); }); } }); </script> </head> <body> <div id="event"><div>示例代碼</div> <pre> obj3.seen = new Date(2013, 0, 1, 0, 0, 0); //觸發time_updated事件 obj3.seen = new Date(2013, 0, 2, 0, 0, 0); //觸發time_updated事件 obj3.seen = new Date(2013, 0, 3, 0, 0, 0); //觸發time_updated事件 obj3.seen = new Date(2013, 0, 4, 0, 0, 0); //觸發time_updated事件 obj3.seen = new Date(2013, 0, 5, 0, 0, 0); //觸發time_updated事件 obj3.seen = new Date(2013, 0, 6, 0, 0, 0); //觸發time_updated事件 obj3.seen = new Date(2013, 0, 7, 0, 0, 0); //觸發time_updated事件 </pre> </div> <div id="seen"></div> <div id="results"></div> </body> </html>

運行代碼

頁面運行結果如下圖所示(在Chrome Canary或Chrome Dev Channel(25.0.1337.0 dev-m以上)版本的瀏覽器中)

從這個結果中我們可以看出,在回調函數中獲取到的屬性值為同一個屬性值(2013年1月7日)。為了強制獲取事件觸發后立即設置的屬性值,我們需要使用Object.deliverChangeRecords方法。

在如下所示的代碼中,每次修改了屬性值后,即調用Object.deliverChangeRecords方法立即調用回調函數。

obj4.seen = new Date(2013, 0, 1, 0, 0, 0); //觸發time_updated事件Object.deliverChangeRecords(output); //調用回調函數obj4.seen = new Date(2013, 0, 2, 0, 0, 0); //觸發time_updated事件Object.deliverChangeRecords(output); //調用回調函數obj4.seen = new Date(2013, 0, 3, 0, 0, 0); //觸發time_updated事件Object.deliverChangeRecords(output); //調用回調函數obj4.seen = new Date(2013, 0, 4, 0, 0, 0); //觸發time_updated事件Object.deliverChangeRecords(output); //調用回調函數obj4.seen = new Date(2013, 0, 5, 0, 0, 0); //觸發time_updated事件Object.deliverChangeRecords(output); //調用回調函數obj4.seen = new Date(2013, 0, 6, 0, 0, 0); //觸發time_updated事件Object.deliverChangeRecords(output); //調用回調函數obj4.seen = new Date(2013, 0, 7, 0, 0, 0); //觸發time_updated事件 <!DOCTYPE html> <head> <title>Object.observer API代碼示例頁面</title> <style> table, td, th { border: 2px #000000 solid; } </style> <script> window.addEventListener('DOMContentLoaded',function() { if (!Object.observe) { alert('您的瀏覽器不支持Object.observe API。請使用Chrome Canary或Chrome Dev Channel(25.0.1337.0 dev-m以上)版本的瀏覽器,并啟用“啟用實驗性 JavaScript”選項。'); return; } var obj4 = {_time: new Date(0)}; var notifier = Object.getNotifier(obj4); Object.defineProperties(obj4, { _time: { enumerable: false, configrable: false }, seen: { set: function(val) { var notifier = Object.getNotifier(this); notifier.notify({ type: 'time_updated', // 時間更新イベントの定義 name: 'seen', oldValue: this._time }); this._time = val; }, get: function() { return this._time; } } }); Object.observe(obj4, output); obj4.seen = new Date(2013, 0, 1, 0, 0, 0); //觸發time_updated事件 Object.deliverChangeRecords(output); //調用回調函數 obj4.seen = new Date(2013, 0, 2, 0, 0, 0); //觸發time_updated事件 Object.deliverChangeRecords(output); //調用回調函數 obj4.seen = new Date(2013, 0, 3, 0, 0, 0); //觸發time_updated事件 Object.deliverChangeRecords(output); //調用回調函數 obj4.seen = new Date(2013, 0, 4, 0, 0, 0); //觸發time_updated事件 Object.deliverChangeRecords(output); //調用回調函數 obj4.seen = new Date(2013, 0, 5, 0, 0, 0); //觸發time_updated事件 Object.deliverChangeRecords(output); //調用回調函數 obj4.seen = new Date(2013, 0, 6, 0, 0, 0); //觸發time_updated事件 Object.deliverChangeRecords(output); //調用回調函數 obj4.seen = new Date(2013, 0, 7, 0, 0, 0); //觸發time_updated事件 function output (changes) { var results = document.getElementById('results'); var table = document.createElement('table'); results.appendChild(table); var caption = document.createElement('caption'); caption.innerText = '監視到的事件列表'; table.appendChild(caption); var thead = document.createElement('thead'); thead.innerHTML = '<tr><th>序號</th><th>操作種類</th><th>屬性名</th><th>修改前的屬性值</th><th>修改后的屬性值</th></tr>'; table.appendChild(thead); changes.forEach(function(change, i) { var tr = document.createElement('tr'); tr.innerHTML = '<td>' + i + '</td><td>' + change.type + '</td><td>' + change.name + '</td><td>' + change.oldValue + '</td><td>' + change.object[change.name] + '</td>'; table.appendChild(tr); }); } }); </script> </head> <body> <div id="event"><div>示例代碼</div> <pre> obj4.seen = new Date(2013, 0, 1, 0, 0, 0); //觸發time_updated事件 Object.deliverChangeRecords(output); //調用回調函數 obj4.seen = new Date(2013, 0, 2, 0, 0, 0); //觸發time_updated事件 Object.deliverChangeRecords(output); //調用回調函數 obj4.seen = new Date(2013, 0, 3, 0, 0, 0); //觸發time_updated事件 Object.deliverChangeRecords(output); //調用回調函數 obj4.seen = new Date(2013, 0, 4, 0, 0, 0); //觸發time_updated事件 Object.deliverChangeRecords(output); //調用回調函數 obj4.seen = new Date(2013, 0, 5, 0, 0, 0); //觸發time_updated事件 Object.deliverChangeRecords(output); //調用回調函數 obj4.seen = new Date(2013, 0, 6, 0, 0, 0); //觸發time_updated事件 Object.deliverChangeRecords(output); //調用回調函數 obj4.seen = new Date(2013, 0, 7, 0, 0, 0); //觸發time_updated事件 </pre> </div> <div id="seen"></div> <div id="results"></div> </body> </html>

運行代碼

頁面運行結果如下圖所示(在Chrome Canary或Chrome Dev Channel(25.0.1337.0 dev-m以上)版本的瀏覽器中)

從這個結果中我們可以看出,每次執行Object.deliverChangeRecords方法時都將調用回調函數在頁面中輸出修改后的屬性值。

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的使用Object.observe 实现数据绑定的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。