首頁 web前端 js教程 實作非常簡單的js雙向資料綁定_javascript技巧

實作非常簡單的js雙向資料綁定_javascript技巧

May 16, 2016 pm 03:33 PM

雙向資料綁定指的就是,綁定物件屬性的改變到使用者介面的變化的能力,反之亦然。換種說法,如果我們有user物件和一個name屬性,一旦我們賦了一個新值給user.name,在UI上就會顯示新的名稱了。同樣地,如果UI包含了一個輸入使用者名稱的輸入框,輸入一個新值就應該會使user物件的name屬性做出對應的改變。

許多熱門的JS框架客戶端如Ember.js,Angular.js 或KnockoutJS ,都在最新特性上刊登了雙向資料綁定。這並不意味著從零實現它很難,也不是說需要這些功能的時候,採用這些框架是唯一的選擇。下面的想法其實很基礎,可以被認為是3步驟計畫:

我們需要一個UI元素和屬性相互綁定的方法
我們需要監視屬性和UI元素的變化
我們需要讓所有綁定的物件和元素都能感知到變化

還是有很多方法能夠實現上面的想法,有一個簡單有效的方法就是使用PubSub模式。 這個想法很簡單:我們使用資料特性來為HTML程式碼進行綁定,所有被綁定在一起的JavaScript物件和DOM元素都會訂閱一個PubSub物件。只要JavaScript物件或一個HTML輸入元素監聽到資料的變化時,就會觸發綁定到PubSub物件上的事件,從而其他綁定的物件和元素都會做出對應的變更。

用jQuery做一個簡單的實作

對於DOM事件的訂閱和發布,用jQuery實現起來是非常簡單的,接下來我們就是用Jquery比如下面:

function DataBinder( object_id ) {
 // Use a jQuery object as simple PubSub
 var pubSub = jQuery({});
 // We expect a `data` element specifying the binding
 // in the form: data-bind-<object_id>="<property_name>"
 var data_attr = "bind-" + object_id,
  message = object_id + ":change";
 // Listen to change events on elements with the data-binding attribute and proxy
 // them to the PubSub, so that the change is "broadcasted" to all connected objects
 jQuery( document ).on( "change", "[data-" + data_attr + "]", function( evt ) {
 var $input = jQuery( this );
 pubSub.trigger( message, [ $input.data( data_attr ), $input.val() ] );
 });
 // PubSub propagates changes to all bound elements, setting value of
 // input tags or HTML content of other tags
 pubSub.on( message, function( evt, prop_name, new_val ) {
 jQuery( "[data-" + data_attr + "=" + prop_name + "]" ).each( function() {
  var $bound = jQuery( this );
  if ( $bound.is("input, textarea, select") ) {
  $bound.val( new_val );
  } else {
  $bound.html( new_val );
  }
 });
 });
 return pubSub;
}
登入後複製

對於上面這個實作來說,以下是一個User模型的最簡單的實作方法:

function User( uid ) {
 var binder = new DataBinder( uid ),
  user = {
  attributes: {},
  // The attribute setter publish changes using the DataBinder PubSub
  set: function( attr_name, val ) {
   this.attributes[ attr_name ] = val;
   binder.trigger( uid + ":change", [ attr_name, val, this ] );
  },
  get: function( attr_name ) {
   return this.attributes[ attr_name ];
  },
  _binder: binder
  };
 // Subscribe to the PubSub
 binder.on( uid + ":change", function( evt, attr_name, new_val, initiator ) {
 if ( initiator !== user ) {
  user.set( attr_name, new_val );
 }
 });
 return user;
}
登入後複製

現在我們如果想要將User模型屬性綁定到UI上,我們只需要將適合的資料特性綁定到對應的HTML元素上。

// javascript
var user = new User( 123 );
user.set( "name", "Wolfgang" );
// html
<input type="number" data-bind-123="name" />
登入後複製

這樣輸入值會自動對應到user物件的name屬性,反之

亦然。到此這個簡單實作就完成囉!

不需要jQuery的實作

在現今大多數的專案裡,可能已經使用了jQuery,因此上面的範例完全可以接受。不過,如果我們需要試著向另一個極端做,並且還刪除對jQuery的依賴,那麼怎麼做呢?好,證實一下這麼做並不難(尤其是在我們限制只支援IE 8以上版本的情況下)。最終,我們必須使用一般的javascript實作一個客製化的PubSub並且保留了DOM事件:

function DataBinder( object_id ) {
 // Create a simple PubSub object
 var pubSub = {
  callbacks: {},
  on: function( msg, callback ) {
   this.callbacks[ msg ] = this.callbacks[ msg ] || [];
   this.callbacks[ msg ].push( callback );
  },
  publish: function( msg ) {
   this.callbacks[ msg ] = this.callbacks[ msg ] || []
   for ( var i = , len = this.callbacks[ msg ].length; i < len; i++ ) {
   this.callbacks[ msg ][ i ].apply( this, arguments );
   }
  }
  },
  data_attr = "data-bind-" + object_id,
  message = object_id + ":change",
  changeHandler = function( evt ) {
  var target = evt.target || evt.srcElement, // IE compatibility
   prop_name = target.getAttribute( data_attr );
  if ( prop_name && prop_name !== "" ) {
   pubSub.publish( message, prop_name, target.value );
  }
  };
 // Listen to change events and proxy to PubSub
 if ( document.addEventListener ) {
 document.addEventListener( "change", changeHandler, false );
 } else {
 // IE uses attachEvent instead of addEventListener
 document.attachEvent( "onchange", changeHandler );
 }
 // PubSub propagates changes to all bound elements
 pubSub.on( message, function( evt, prop_name, new_val ) {
 var elements = document.querySelectorAll("[" + data_attr + "=" + prop_name + "]"),
  tag_name;
 for ( var i = , len = elements.length; i < len; i++ ) {
  tag_name = elements[ i ].tagName.toLowerCase();
  if ( tag_name === "input" || tag_name === "textarea" || tag_name === "select" ) {
  elements[ i ].value = new_val;
  } else {
  elements[ i ].innerHTML = new_val;
  }
 }
 });
 return pubSub;
}
登入後複製

除了設定器裡呼叫 jQuery的trigger方法外,模型可以保持一樣。呼叫trigger方法將取代為呼叫我們定制的具有不同特徵的PubSub的publish方法:

// In the model's setter:
function User( uid ) {
 // ...
 user = {
 // ...
 set: function( attr_name, val ) {
  this.attributes[ attr_name ] = val;
  // Use the `publish` method
  binder.publish( uid + ":change", attr_name, val, this );
 }
 }
 // ...
}
登入後複製

我們又一次通過一百行不到,又可維護的純javascript完成了我們想要的結果。

以上內容就是關於js雙向資料綁定的相關教程,希望對大家學習有所幫助。

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

前端熱敏紙小票打印遇到亂碼問題怎麼辦? 前端熱敏紙小票打印遇到亂碼問題怎麼辦? Apr 04, 2025 pm 02:42 PM

前端熱敏紙小票打印的常見問題與解決方案在前端開發中,小票打印是一個常見的需求。然而,很多開發者在實...

誰得到更多的Python或JavaScript? 誰得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? 如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

如何實現視差滾動和元素動畫效果,像資生堂官網那樣?
或者:
怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? 如何實現視差滾動和元素動畫效果,像資生堂官網那樣? 或者: 怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? Apr 04, 2025 pm 05:36 PM

實現視差滾動和元素動畫效果的探討本文將探討如何實現類似資生堂官網(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript難以學習嗎? JavaScript難以學習嗎? Apr 03, 2025 am 12:20 AM

學習JavaScript不難,但有挑戰。 1)理解基礎概念如變量、數據類型、函數等。 2)掌握異步編程,通過事件循環實現。 3)使用DOM操作和Promise處理異步請求。 4)避免常見錯誤,使用調試技巧。 5)優化性能,遵循最佳實踐。

前端開發中如何實現類似 VSCode 的面板拖拽調整功能? 前端開發中如何實現類似 VSCode 的面板拖拽調整功能? Apr 04, 2025 pm 02:06 PM

探索前端中類似VSCode的面板拖拽調整功能的實現在前端開發中,如何實現類似於VSCode...

console.log輸出結果差異:兩次調用為何不同? console.log輸出結果差異:兩次調用為何不同? Apr 04, 2025 pm 05:12 PM

深入探討console.log輸出差異的根源本文將分析一段代碼中console.log函數輸出結果的差異,並解釋其背後的原因。 �...

See all articles