Heim  >  Artikel  >  Web-Frontend  >  Implementieren Sie sehr einfache js-Fähigkeiten zur bidirektionalen Datenbindung_Javascript

Implementieren Sie sehr einfache js-Fähigkeiten zur bidirektionalen Datenbindung_Javascript

WBOY
WBOYOriginal
2016-05-16 15:33:202285Durchsuche

Zwei-Wege-Datenbindung bezieht sich auf die Fähigkeit, Änderungen in Objekteigenschaften an Änderungen in der Benutzeroberfläche zu binden und umgekehrt. Mit anderen Worten: Wenn wir ein Benutzerobjekt und ein Namensattribut haben, wird der neue Name auf der Benutzeroberfläche angezeigt, sobald wir user.name einen neuen Wert zuweisen. Wenn die Benutzeroberfläche ebenfalls ein Eingabefeld für den Namen des Benutzers enthält, sollte die Eingabe eines neuen Werts dazu führen, dass sich die Namenseigenschaft des Benutzerobjekts entsprechend ändert.

Viele beliebte JS-Framework-Clients wie Ember.js, Angular.js oder KnockoutJS haben in ihren neuesten Funktionen eine bidirektionale Datenbindung implementiert. Dies bedeutet nicht, dass es schwierig ist, es von Grund auf zu implementieren, und auch nicht, dass die Übernahme dieser Frameworks die einzige Option ist, wenn diese Funktionen benötigt werden. Die folgende Idee ist eigentlich sehr einfach und kann als 3-Stufen-Plan betrachtet werden:

Wir brauchen eine Möglichkeit, UI-Elemente und -Attribute miteinander zu verbinden
Wir müssen Änderungen an Eigenschaften und UI-Elementen überwachen
Wir müssen alle gebundenen Objekte und Elemente auf Änderungen aufmerksam machen

Es gibt noch viele Möglichkeiten, die oben genannte Idee umzusetzen. Eine einfache und effektive Möglichkeit ist die Verwendung des PubSub-Modus. Die Idee ist einfach: Wir verwenden Datenattribute, um HTML-Code zu binden, und alle miteinander verbundenen JavaScript-Objekte und DOM-Elemente abonnieren ein PubSub-Objekt. Solange ein JavaScript-Objekt oder ein HTML-Eingabeelement auf Datenänderungen lauscht, wird das an das PubSub-Objekt gebundene Ereignis ausgelöst und andere gebundene Objekte und Elemente nehmen entsprechende Änderungen vor.

Verwenden Sie jQuery, um eine einfache Implementierung durchzuführen

Zum Abonnieren und Veröffentlichen von DOM-Ereignissen ist es sehr einfach, es mit jQuery zu implementieren. Als nächstes verwenden wir Jquery, wie zum Beispiel das Folgende:

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;
}

Für die obige Implementierung ist das Folgende die einfachste Implementierungsmethode eines Benutzermodells:

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;
}

Wenn wir nun die Benutzermodellattribute an die Benutzeroberfläche binden möchten, müssen wir nur die entsprechenden Datenattribute an die entsprechenden HTML-Elemente binden.

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

Auf diese Weise wird der Eingabewert automatisch dem Namensattribut des Benutzerobjekts zugeordnet und umgekehrt

Das Gleiche. Diese einfache Implementierung ist abgeschlossen!

Keine jQuery-Implementierung erforderlich

In den meisten Projekten wird jQuery heute wahrscheinlich bereits verwendet, daher ist das obige Beispiel völlig akzeptabel. Was aber, wenn wir versuchen müssen, ins andere Extrem zu gehen und auch die Abhängigkeit von jQuery zu beseitigen? Nun, es ist nicht so schwer zu beweisen (vor allem, da wir den Support auf IE 8 und höher beschränken). Letztendlich müssen wir ein benutzerdefiniertes PubSub mit normalem Javascript implementieren und DOM-Ereignisse beibehalten:

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;
}

Das Modell kann bis auf den Aufruf der jQuery-Trigger-Methode im Setter gleich bleiben. Der Aufruf der Trigger-Methode wird durch den Aufruf der Publish-Methode unseres angepassten PubSub mit anderen Eigenschaften ersetzt:

// 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 );
 }
 }
 // ...
}

Wir haben erneut die gewünschten Ergebnisse mit weniger als hundert Zeilen wartbarem reinem JavaScript erzielt.

Der obige Inhalt ist ein Tutorial zur bidirektionalen Datenbindung von js. Ich hoffe, dass es für alle hilfreich ist.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn