Rumah  >  Artikel  >  hujung hadapan web  >  Melaksanakan pengikatan dua hala kemahiran javascript data_javascript dengan mudah

Melaksanakan pengikatan dua hala kemahiran javascript data_javascript dengan mudah

WBOY
WBOYasal
2016-05-16 15:32:411328semak imbas

Pengikatan data dua hala bermakna apabila sifat objek berubah, UI yang sepadan boleh ditukar pada masa yang sama, dan begitu juga sebaliknya. Dalam erti kata lain, jika kita mempunyai objek pengguna yang mempunyai sifat nama, apabila anda menetapkan nilai baharu kepada nama pengguna, UI akan memaparkan nilai baharu. Begitu juga, jika UI mengandungi kotak input untuk nama pengguna, memasukkan nilai baharu akan menyebabkan sifat nama objek pengguna berubah dengan sewajarnya.

Banyak rangka kerja javascript yang popular, seperti Ember.js, Angular.js atau KnockoutJS, mempromosikan pengikatan data dua hala sebagai salah satu ciri utamanya. Ini tidak bermakna melaksanakannya dari awal adalah sukar, dan juga tidak bermakna menggunakan rangka kerja ini adalah satu-satunya pilihan kami apabila kami memerlukan fungsi ini. Idea asas di dalamnya sebenarnya agak asas, dan pelaksanaannya boleh diringkaskan dalam tiga perkara berikut:

  • Kami memerlukan cara untuk menentukan elemen UI yang terikat pada sifat mana.
  • Kami perlu memantau perubahan dalam sifat dan UI
  • Kami perlu menyebarkan perubahan kepada semua objek terikat dan elemen UI.

Walaupun terdapat banyak cara untuk mencapai mata ini, cara yang mudah dan cekap ialah kami melaksanakannya melalui corak penerbit-pelanggan. Kaedahnya mudah: kita boleh menggunakan atribut data tersuai sebagai atribut yang perlu diikat dalam kod HTML. Semua objek JavaScript dan elemen DOM yang diikat bersama akan melanggan objek publish-subscribe ini. Pada bila-bila masa kami mengesan perubahan sama ada dalam objek Javascript atau elemen input HTML, kami menghantar proksi acara kepada objek publish-subscribe, dan kemudian lulus dan menyiarkan semua perubahan yang berlaku dalam objek dan elemen terikat melaluinya.

Contoh mudah dilaksanakan dengan jQuery

Agak mudah dan mudah untuk melaksanakan perkara yang kami bincangkan di atas melalui jQuery, kerana sebagai perpustakaan yang popular, ia membolehkan kami melanggan dan menerbitkan acara DOM dengan mudah, dan kami juga boleh menyesuaikan satu:

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 chagne events on elements with data-binding attribute and proxy
  // then to the PubSub, so that the change is "broadcasted" to all connected objects
  jQuery(document).on("change","[data-]"+data_attr+"]",function(eve){
    var $input=jQuery(this);

    pubSub.trigger(message,[$input.data(data_attr),$input.val()]);
  });

  // PubSub propagates chagnes to all bound elemetns,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("")){
        $bound.val(new_val);
      }else{
        $bound.html(new_val);
      }
    });
  });
  return pubSub;
}

Bagi objek JavaScript, berikut ialah contoh pelaksanaan model data pengguna yang minimum:

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 PubSub
  binder.on(uid+":change",function(evt,attr_name,new_val,initiator){
    if(initiator!==user){
      user.set(attr_name,new_val);
    }
  });

  return user;
}

Sekarang, apabila kami ingin mengikat sifat objek pada UI, kami hanya menetapkan atribut data yang sesuai pada elemen HTML yang sepadan.

// javascript 
var user=new User(123);
user.set("name","Wolfgang");

// html
<input type="number" data-bind-123="name" />

Perubahan nilai dalam kotak input secara automatik akan dipetakan kepada atribut nama pengguna, dan begitu juga sebaliknya. Anda sudah selesai!

Pelaksanaan yang tidak memerlukan jQuery

Kebanyakan projek pada masa kini biasanya menggunakan jQuery, jadi contoh di atas boleh diterima sepenuhnya. Tetapi bagaimana jika kita perlu bebas sepenuhnya daripada jQuery? Sebenarnya, ia tidak sukar untuk dilakukan (terutama apabila kami hanya menyediakan sokongan untuk IE8 dan ke atas). Akhir sekali, kita hanya perlu memerhati peristiwa DOM melalui corak penerbit-pelanggan.

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 = 0, 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, // IE8 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 {
  // IE8 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 = 0, 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;
}

Model data boleh kekal tidak berubah, kecuali untuk panggilan kepada kaedah pencetus dalam jQuery dalam setter, yang boleh digantikan dengan kaedah penerbitan tersuai kami dalam PubSub.

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

 // ...
}

Kami menjelaskannya melalui contoh, dan sekali lagi mencapai hasil yang kami inginkan dengan kurang daripada seratus baris JavaScript tulen yang boleh diselenggara Kami berharap ia akan membantu semua orang dalam merealisasikan pengikatan dua hala data JavaScript.

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn