關於javascript實現資料雙向綁定的三種方法分享
本篇文章主要介紹了javascript實現資料雙向綁定的三種方式小結,前端的視圖層和資料層有時需要實現雙向綁定,目前實作數據雙向綁定主要有三種,有興趣的可以了解一下。
前端資料的雙向綁定方法
前端的視圖層和資料層有時需要實作雙向綁定(two-way-binding),例如mvvm框架,資料驅動視圖,視圖狀態機等,研究了幾個目前主流的資料雙向綁定框架,總結了下。目前實作資料雙向綁定主要有以下三種。
1、手動綁定
比較舊的實作方式,有點像觀察者程式設計模式,主要想法是透過在資料物件上定義get和set方法(當然還有其它方法),呼叫時手動呼叫get或set數據,改變資料後出發UI層的渲染操作;以視圖驅動資料變更的場景主要應用與input、select、textarea等元素,當UI層變化時,透過監聽dom的change,keypress,keyup等事件來出發事件改變資料層的資料。整個過程均透過函數呼叫完成。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>data-binding-method-set</title> </head> <body> <input q-value="value" type="text" id="input"> <p q-text="value" id="el"></p> <script> var elems = [document.getElementById('el'), document.getElementById('input')]; var data = { value: 'hello!' }; var command = { text: function(str){ this.innerHTML = str; }, value: function(str){ this.setAttribute('value', str); } }; var scan = function(){ /** * 扫描带指令的节点属性 */ for(var i = 0, len = elems.length; i < len; i++){ var elem = elems[i]; elem.command = []; for(var j = 0, len1 = elem.attributes.length; j < len1; j++){ var attr = elem.attributes[j]; if(attr.nodeName.indexOf('q-') >= 0){ /** * 调用属性指令,这里可以使用数据改变检测 */ command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]); elem.command.push(attr.nodeName.slice(2)); } } } } /** * 设置数据后扫描 */ function mvSet(key, value){ data[key] = value; scan(); } /** * 数据绑定监听 */ elems[1].addEventListener('keyup', function(e){ mvSet('value', e.target.value); }, false); scan(); /** * 改变数据更新视图 */ setTimeout(function(){ mvSet('value', 'fuck'); },1000) </script> </body> </html>
2、髒檢查機制
以典型的mvvm框架angularjs為代表,angular透過檢查髒資料來進行UI層的操作更新。關於angular的髒檢測,有幾點需要了解一些: - 髒檢測機制並不是使用定時檢測。 - 髒檢測的時機是在資料發生變化時進行。 - angular對常用的dom事件,xhr事件等做了封裝, 在裡面觸發進入angular的digest流程。 - 在digest流程裡面, 會從rootscope開始遍歷, 檢查所有的watcher。 (關於angular的具體設計可以看其他文檔,這裡只討論資料綁定),那我們看下臟檢測該如何去做:主要是透過設定的資料來需找與該資料相關的所有元素,然後再比較資料變化,如果變化則進行指令操作
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>data-binding-drity-check</title> </head> <body> <input q-event="value" ng-bind="value" type="text" id="input"> <p q-event="text" ng-bind="value" id="el"></p> <script> var elems = [document.getElementById('el'), document.getElementById('input')]; var data = { value: 'hello!' }; var command = { text: function(str) { this.innerHTML = str; }, value: function(str) { this.setAttribute('value', str); } }; var scan = function(elems) { /** * 扫描带指令的节点属性 */ for (var i = 0, len = elems.length; i < len; i++) { var elem = elems[i]; elem.command = {}; for (var j = 0, len1 = elem.attributes.length; j < len1; j++) { var attr = elem.attributes[j]; if (attr.nodeName.indexOf('q-event') >= 0) { /** * 调用属性指令 */ var dataKey = elem.getAttribute('ng-bind') || undefined; /** * 进行数据初始化 */ command[attr.nodeValue].call(elem, data[dataKey]); elem.command[attr.nodeValue] = data[dataKey]; } } } } /** * 脏循环检测 * @param {[type]} elems [description] * @return {[type]} [description] */ var digest = function(elems) { /** * 扫描带指令的节点属性 */ for (var i = 0, len = elems.length; i < len; i++) { var elem = elems[i]; for (var j = 0, len1 = elem.attributes.length; j < len1; j++) { var attr = elem.attributes[j]; if (attr.nodeName.indexOf('q-event') >= 0) { /** * 调用属性指令 */ var dataKey = elem.getAttribute('ng-bind') || undefined; /** * 进行脏数据检测,如果数据改变,则重新执行指令,否则跳过 */ if(elem.command[attr.nodeValue] !== data[dataKey]){ command[attr.nodeValue].call(elem, data[dataKey]); elem.command[attr.nodeValue] = data[dataKey]; } } } } } /** * 初始化数据 */ scan(elems); /** * 可以理解为做数据劫持监听 */ function $digest(value){ var list = document.querySelectorAll('[ng-bind='+ value + ']'); digest(list); } /** * 输入框数据绑定监听 */ if(document.addEventListener){ elems[1].addEventListener('keyup', function(e) { data.value = e.target.value; $digest(e.target.getAttribute('ng-bind')); }, false); }else{ elems[1].attachEvent('onkeyup', function(e) { data.value = e.target.value; $digest(e.target.getAttribute('ng-bind')); }, false); } setTimeout(function() { data.value = 'fuck'; /** * 这里问啥还要执行$digest这里关键的是需要手动调用$digest方法来启动脏检测 */ $digest('value'); }, 2000) </script> </body> </html>
3、前端資料劫持(Hijacking)
第三種方法則是avalon等框架所使用的數據劫持方式。基本想法是使用Object.defineProperty對資料物件做屬性get和set的監聽,當有資料讀取和賦值運算時則呼叫節點的指令,這樣使用最通用的=等號賦值就可以了。具體實作如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>data-binding-hijacking</title> </head> <body> <input q-value="value" type="text" id="input"> <p q-text="value" id="el"></p> <script> var elems = [document.getElementById('el'), document.getElementById('input')]; var data = { value: 'hello!' }; var command = { text: function(str) { this.innerHTML = str; }, value: function(str) { this.setAttribute('value', str); } }; var scan = function() { /** * 扫描带指令的节点属性 */ for (var i = 0, len = elems.length; i < len; i++) { var elem = elems[i]; elem.command = []; for (var j = 0, len1 = elem.attributes.length; j < len1; j++) { var attr = elem.attributes[j]; if (attr.nodeName.indexOf('q-') >= 0) { /** * 调用属性指令 */ command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]); elem.command.push(attr.nodeName.slice(2)); } } } } var bValue; /** * 定义属性设置劫持 */ var defineGetAndSet = function(obj, propName) { try { Object.defineProperty(obj, propName, { get: function() { return bValue; }, set: function(newValue) { bValue = newValue; scan(); }, enumerable: true, configurable: true }); } catch (error) { console.log("browser not supported."); } } /** * 初始化数据 */ scan(); /** * 可以理解为做数据劫持监听 */ defineGetAndSet(data, 'value'); /** * 数据绑定监听 */ if(document.addEventListener){ elems[1].addEventListener('keyup', function(e) { data.value = e.target.value; }, false); }else{ elems[1].attachEvent('onkeyup', function(e) { data.value = e.target.value; }, false); } setTimeout(function() { data.value = 'fuck'; }, 2000) </script> </body> </html>
但值得注意的是defineProperty支援IE8以上的瀏覽器,這裡可以使用defineGetter 和 defineSetter 來做相容但是瀏覽器相容性的原因,直接用defineProperty就可以了。至於IE8瀏覽器仍需要使用其它方法來做hack。如下程式碼可以對IE8進行hack,defineProperty支援IE8。例如使用es5-shim.js就可以了。 (IE8以下瀏覽器忽略)
4、小結
#首先這裡的例子只是簡單的實現,讀者可以深入感受三種方式的異同點,複雜的框架也是透過這樣的基本想法滾雪球滾大的。
以上是關於javascript實現資料雙向綁定的三種方法分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

DDREASE是一種用於從檔案或區塊裝置(如硬碟、SSD、RAM磁碟、CD、DVD和USB儲存裝置)復原資料的工具。它將資料從一個區塊設備複製到另一個區塊設備,留下損壞的資料區塊,只移動好的資料區塊。 ddreasue是一種強大的恢復工具,完全自動化,因為它在恢復操作期間不需要任何干擾。此外,由於有了ddasue地圖文件,它可以隨時停止和恢復。 DDREASE的其他主要功能如下:它不會覆寫恢復的數據,但會在迭代恢復的情況下填補空白。但是,如果指示工具明確執行此操作,則可以將其截斷。將資料從多個檔案或區塊還原到單

0.這篇文章乾了啥?提出了DepthFM:一個多功能且快速的最先進的生成式單目深度估計模型。除了傳統的深度估計任務外,DepthFM還展示了在深度修復等下游任務中的最先進能力。 DepthFM效率高,可以在少數推理步驟內合成深度圖。以下一起來閱讀這項工作~1.論文資訊標題:DepthFM:FastMonocularDepthEstimationwithFlowMatching作者:MingGui,JohannesS.Fischer,UlrichPrestel,PingchuanMa,Dmytr

如果您需要了解如何在Excel中使用具有多個條件的篩選功能,以下教學將引導您完成對應步驟,確保您可以有效地篩選資料和排序資料。 Excel的篩選功能是非常強大的,能夠幫助您從大量資料中提取所需的資訊。這個功能可以根據您設定的條件,過濾資料並只顯示符合條件的部分,讓資料的管理變得更有效率。透過使用篩選功能,您可以快速找到目標數據,節省了尋找和整理數據的時間。這個功能不僅可以應用在簡單的資料清單上,還可以根據多個條件進行篩選,幫助您更精準地定位所需資訊。總的來說,Excel的篩選功能是一個非常實用的

谷歌力推的JAX在最近的基準測試中表現已經超過Pytorch和TensorFlow,7項指標排名第一。而且測試並不是JAX性能表現最好的TPU上完成的。雖然現在在開發者中,Pytorch依然比Tensorflow更受歡迎。但未來,也許有更多的大型模型會基於JAX平台進行訓練和運行。模型最近,Keras團隊為三個後端(TensorFlow、JAX、PyTorch)與原生PyTorch實作以及搭配TensorFlow的Keras2進行了基準測試。首先,他們為生成式和非生成式人工智慧任務選擇了一組主流

在iPhone上面臨滯後,緩慢的行動數據連線?通常,手機上蜂窩互聯網的強度取決於幾個因素,例如區域、蜂窩網絡類型、漫遊類型等。您可以採取一些措施來獲得更快、更可靠的蜂窩網路連線。修復1–強制重啟iPhone有時,強制重啟設備只會重置許多內容,包括蜂窩網路連線。步驟1–只需按一次音量調高鍵並放開即可。接下來,按降低音量鍵並再次釋放它。步驟2–過程的下一部分是按住右側的按鈕。讓iPhone完成重啟。啟用蜂窩數據並檢查網路速度。再次檢查修復2–更改資料模式雖然5G提供了更好的網路速度,但在訊號較弱

哭死啊,全球狂煉大模型,一網路的資料不夠用,根本不夠用。訓練模型搞得跟《飢餓遊戲》似的,全球AI研究者,都在苦惱怎麼才能餵飽這群資料大胃王。尤其在多模態任務中,這問題尤其突出。一籌莫展之際,來自人大系的初創團隊,用自家的新模型,率先在國內把「模型生成數據自己餵自己」變成了現實。而且還是理解側和生成側雙管齊下,兩側都能產生高品質、多模態的新數據,對模型本身進行數據反哺。模型是啥?中關村論壇上剛露面的多模態大模型Awaker1.0。團隊是誰?智子引擎。由人大高瓴人工智慧學院博士生高一鑷創立,高

特斯拉機器人Optimus最新影片出爐,已經可以在工廠裡打工了。正常速度下,它分揀電池(特斯拉的4680電池)是這樣的:官方還放出了20倍速下的樣子——在小小的「工位」上,揀啊揀啊揀:這次放出的影片亮點之一在於Optimus在廠子裡完成這項工作,是完全自主的,全程沒有人為的干預。而且在Optimus的視角之下,它還可以把放歪了的電池重新撿起來放置,主打一個自動糾錯:對於Optimus的手,英偉達科學家JimFan給出了高度的評價:Optimus的手是全球五指機器人裡最靈巧的之一。它的手不僅有觸覺

這週,由OpenAI、微軟、貝佐斯和英偉達投資的機器人公司FigureAI宣布獲得接近7億美元的融資,計劃在未來一年內研發出可獨立行走的人形機器人。而特斯拉的擎天柱也屢屢傳出好消息。沒人懷疑,今年會是人形機器人爆發的一年。一家位於加拿大的機器人公司SanctuaryAI最近發布了一款全新的人形機器人Phoenix。官方號稱它能以和人類一樣的速率自主完成許多工作。世界上第一台能以人類速度自主完成任務的機器人Pheonix可以輕輕地抓取、移動並優雅地將每個物件放置在它的左右兩側。它能夠自主辨識物體的
