2013-03-09 180 views
18

如何在jQuery中實現簡單的雙向數據綁定? 類似knockoutJS,但以最簡單的形式。場景 - 將JSON對象綁定到表格行(每個字段爲td> input />/td>)。jQuery雙向數據綁定

有什麼建議嗎?

+2

你應該給一個更具體的例子和一些嘗試。 – soyuka 2013-03-09 11:00:15

+1

我做到了。檢查我自己的答案。任何建議,詭計? – kayz1 2013-03-09 17:10:27

+0

http://jquerymy.com/ – 2015-09-03 20:59:58

回答

11

我嘗試 - HTML

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <title>Data Binding</title> 
</head> 
<body> 
    <table id="content-table"> 
     <thead> 
     </thead> 
     <tbody></tbody> 
    </table> 
    <button id="get-data">Get</button> 
    <button id="set-data">Set</button> 

    <script src="../js/vendor/jquery-1.9.1.js"></script> 
    <script src="../js/vendor/jquery-migrate-1.1.1.js"></script> 
    <script src="../js/vendor/watch.js"></script> 
    <script src="../js/dataBinder.js"></script> 
</body> 
</html> 

的JavaScript

var DataBinder = (function ($) { 

    var _$table = null, 
     _objectList = [], 
     _fieldList = [], 
     _objectListLength = -1, 
     _fieldListLength = -1; 

    /* AJAX call or smth. */ 
    var _loadData = function() { 
     var fakeData = [{ 
      name: 'John', 
      surname: 'Doe' 
     }, { 
      name: 'Foo', 
      surname: 'Bar' 
     }]; 

     _objectList = $.map(fakeData, function (element, index) { 
      var elementObject = { 
       _dataBinderId: index, 
       element: element, 
       input: {} 
      }; 

      watch(elementObject.element, function (property, action, newValue) { 
       _setValue.call(elementObject, property, newValue); 
      }); 

      return elementObject; 
     }); 

     _objectListLength = _objectList.length; 
    }; 

    var _getFields = function() { 
     for (var i = 0; i < _objectListLength; i++) { 
      for (var field in _objectList[i].element) { 
       if (!!!~$.inArray(field, _fieldList)) { 
        _fieldList.push(field); 
       } 
      } 
     } 

     _fieldListLength = _fieldList.length; 
    }; 

    var _setValue = function (field, value) { 
     this.input[field].val(value); 
    }; 

    var _bindEvents = function() { 
     $('#get-data').on('click', function() { 
      alert(JSON.stringify(_getRowData())); 
     }); 

     $('#set-data').on('click', function() { 
      _objectList[0].element.name = 'PIPA'; 
      _objectList[1].element.surname = 'BLAAAAAAH'; 
     }); 

     _$table.on('keyup', 'input', function() { 
      var $this = $(this), field = $this.data('field'), source = $this.closest('tr').data('source'); 
      source[field] = $this.val(); 
     }); 
    }; 

    var _getRowData = function() { 
     var elements = []; 

     $.each(_objectList, function() { 
      elements.push(this.element); 
     }); 

     return elements; 
    }; 

    var _generateEditableElements = function() { 
     var rowList = [], headerRow = $('<tr>'); 

     for (var k = 0; k < _fieldListLength; k++) { 
      headerRow.append($('<th>', { 
       text: _fieldList[k].toUpperCase() 
      })); 
     } 
     _$table.find('thead').append(headerRow); 

     for (var i = 0; i < _objectListLength; i++) { 
      var objectData = _objectList[i], currentRow = $('<tr>'); 

      currentRow.data('source', objectData.element); 
      rowList.push(currentRow); 

      for (var j = 0; j < _fieldListLength; j++) { 
       var field = _fieldList[j], $inputElement = $('<input>', { 
        type: 'text', 
        value: objectData.element[field] 
       }); 

       $inputElement.data('field', field); 
       objectData.input[field] = $inputElement; 

       currentRow.append($('<td>').append($inputElement)); 
      } 
     } 

     _$table.find('tbody').append(rowList); 
    }; 

    var init = function ($table) { 
     _$table = $table; 

     _loadData(); 
     _getFields(); 

     _generateEditableElements(); 
     _bindEvents(); 
    }; 

    return { 
     init: init 
    }; 

})(jQuery); 

DataBinder.init($("#content-table")); 

Result

我用驚人Watch.JSHow Does Watch.js Work?

Watch.js now uses Object.observe

下面是另一個例子Easy Two-Way Data Binding in JavaScript

而另一question.

Native JavaScript Data-Binding

+2

Watch.JS看起來不錯,但它使用setInterval進行定期檢查。這對性能來說不是很好... – 2013-12-06 23:41:51

+2

現在它使用Object.observe(如果存在)。 – kayz1 2014-08-29 17:12:16

+0

太棒了!我期待着根據這個新功能測試Watch.js! – 2014-08-30 20:32:28

2

該解決方案是相當簡單的,它可以擴展到具有更復雜的功能性:http://cssshowcase.co.uk/two-way-data-binding-with-jquery/

它的字面結合2個或更多的HTML元素一起,與它的它改變任何元件的內HTML目前的形式和任何輸入的值也適用於每個擁有相同「綁定」屬性值的元素。