2012-08-10 91 views
14

出於好奇,爲了增加我的知識,我想在dom元素和javascript變量之間實現某種雙向數據綁定。平原Javascript雙向數據綁定

我很幸運地找到了一個很好的答案,我的一半問題在這裏@ stackoverflow,導致我這個要點https://gist.github.com/384583,但我仍然無法完成100%的事情。

這裏是我的代碼的例如: http://jsfiddle.net/bpH6Z/

如果您嘗試運行小提琴,然後點擊「瀏覽價值」,你會得到不確定,而我想要得到的實際值對象的屬性。

由於我對javascript的使用經驗不足,我可能做錯了什麼,但是你有什麼想法,爲什麼在_bind()和_watch()調用之後我無法正確讀取屬性'secret'?

免責聲明:正如我所說,我這樣做是因爲我想要更好的JavaScript知識,而且我不打算寫我的框架。所以任何「使用FRAMEWORK X」都是無用的,因爲我可以用angularjs完成工作。

+0

+1純JS) – metadings 2012-08-10 15:16:46

+0

IST $指的是jQuery的?所以它不是普通的JS huh – daslicht 2014-09-02 15:56:04

+0

[如何在JavaScript中實現DOM數據綁定]可能的重複(http://stackoverflow.com/questions/16483560/how-to-implement-dom-data-binding-in-javascript) – Beginner 2015-12-29 14:50:29

回答

5

請嘗試http://jsfiddle.net/bpH6Z/4/

我已經更新了你的重新定義的getter/setter中的Object.prototype .__手錶, 也是目前處理程序需要返回新值。

更新:現在您的處理程序不需要返回新設置的值。

當前代碼:

//Got this great piece of code from https://gist.github.com/384583 
Object.defineProperty(Object.prototype, "__watch", { 
    enumerable: false, 
    configurable: true, 
    writable: false, 
    value: function(prop, handler) { 
     var val = this[prop], 
      getter = function() { 
       return val; 
      }, 
      setter = function(newval) { 
       val = newval; 
       handler.call(this, prop, newval); 
       return newval; 
      }; 

     if (delete this[prop]) { // can't watch constants 
      Object.defineProperty(this, prop, { 
       get: getter, 
       set: setter, 
       enumerable: true, 
       configurable: true 
      }); 
     } 
    } 
}); 

var Controller = function() { 
    //The property is changed whenever the dom element changes value 
    //TODO add a callback ? 
    this._bind = function (DOMelement, propertyName) { 
     //The next line is commented because priority is given to the model 
     //this[propertyName] = $(DOMelement).val(); 
     var _ctrl = this; 
     $(DOMelement).on("change input propertyChange", function(e) { 
      e.preventDefault(); 
      _ctrl[propertyName] = DOMelement.val(); 
     }); 

    }; 

    //The dom element changes values when the propertyName is setted 
    this._watch = function(DOMelement, propertyName) { 
     //__watch triggers when the property changes 
     this.__watch(propertyName, function(property, value) { 
      $(DOMelement).val(value); 
     }); 
    }; 
}; 

var ctrl = new Controller(); 
ctrl.secret = 'null'; 
ctrl._bind($('#text1'), 'secret'); // I want the model to reflect changes in #text1 
ctrl._watch($('#text2'), 'secret'); // I want the dom element #text2 to reflect changes in the model 
$('#button1').click(function() { 
    $('#output').html('Secret is : ' + ctrl.secret); //This gives problems 
}); 

當前HTML:

<html> 
<head></head> 
<body> 
    value: <input type="text" id="text1" /><br /> 
    copy: <input type="text" id="text2" /><br /> 
    <input type="button" id="button1" value="View value"><br /> 
    <span id="output"></span> 
</body> 
</html> 
+0

+1爲返工 – fatmatto 2012-08-10 15:14:11

+0

將這項工作與IE8作爲defineProperty只適用於DOM對象? – Integralist 2013-08-18 16:54:47

+0

@Integralist最有可能不是,但一個應該試試看 - 必須重新啓動到XP – metadings 2013-08-18 19:18:38

3

您傳遞給您的__watch函數的處理程序缺少return語句。

this._watch = function(DOMelement, propertyName) { 
    //__watch triggers when the property changes 
    this.__watch(propertyName, function(property, value) { 
     $(DOMelement).val(value); 
     return value; 
    }) 

} 

因爲newval設置什麼從處理程序返回的年代,這將是undefined沒有說。

+0

+1。點擊,擊敗我吧...我只是最後注意到了這一點 – 2012-08-10 15:05:35

+0

+1爲了消除我的頭痛 – fatmatto 2012-08-10 15:15:59

0

我增強了其多觀察。

http://jsfiddle.net/liyuankui/54vE4/

//The dom element changes values when the propertyName is setted 
this._watch = function(DOMelement, propertyName) { 
    //__watch triggers when the property changes 
    if(watchList.indexOf(DOMelement)<0){ 
     watchList.push(DOMelement); 
    } 
    this.__watch(propertyName, function(property, value) { 
     for(var i=0;i<watchList.length;i++){ 
      var watch=watchList[i]; 
      $(watch).val(value); 
      $(watch).html(value); 
     } 
    }); 
};