2015-06-25 22 views
0

我正在使用module.exports將React.js組件轉換爲Common.js模塊,並且存在從其中一個組件的元素的上下文中訪問「this」的問題方法。module.exports中的「this」的作用域

下面是整個組件。我在問題出現的位置上方發表了評論。起初我嘗試了一個不太詳細的例子,但我認爲這不足以解釋這個問題。

var React = require('react'); 
    var GSAP = require('gsap'); 

    var Psychedelicon = React.createClass({ 

     cycleColors: function() { 
      var touchPlatforms = ['iPhone', 'iPad', 'iPod', 'Android', 'Linux armv7l', 'WinCE']; 
         isTouch = false; 
         iDevice = false; 
         isDroid = false; 
         plat = navigator.platform; 

      if(plat === 'iPhone' || plat === 'iPad' || plat === 'iPod') { 
       isTouch = true; 
       iDevice = true; 
      } 
      else if (plat === 'Linux armv7l' || plat === 'Android') { 
       isTouch = true; 
       isDroid = true; 
      } 
      else { 
       for (var i = 0; i < touchPlatforms.length; i++) { 
        if (plat === touchPlatforms[i]) { 
         isTouch = true; 
         break; 
        } 
        else { 
         isTouch = false; 
        } 
       } 
      } 

      var isIE = false 
       if (navigator.userAgent.toLowerCase().indexOf('msie') > -1 || navigator.userAgent.toLowerCase().indexOf('trident') > -1) { 
       isIE = true 
      } 

      var isFF = false 
       if (navigator.userAgent.toLowerCase().indexOf('firefox') != -1) { 
       isFF = true 
      } 

      if(!isTouch) { 
       var ColorSwirl = function(colorSet,defaultColor,time) { 
        var storedResult; 
        var randomColor = function(theArray) { 
         var result = theArray[Math.floor(Math.random() * (theArray.length))]; 
         if(result === storedResult){ 
          return(defaultColor)       
         } 
         else { 
          storedResult = result; 
          return(result); 
         } 
        } 
        var theLuckyColors = {top:randomColor(colorSet),bottom:randomColor(colorSet)}; 
        var swirl = function(){ 
    //!!!!On this line the problem occurs onUpdateParams must reference the element accepting the execution event (onMouseEneter) 
         TweenLite.to(theLuckyColors, time, {colorProps:{top:randomColor(colorSet), bottom:randomColor(colorSet)}, onUpdate:colorize, onUpdateParams:[this],onComplete:swirl}); 
        } 
gradients 
        var colorize = function(el) { 
         if(isIE) { 
          TweenLite.set(el, { 
           backgroundImage:'-ms-radial-gradient(center,circle cover,' + theLuckyColors.top + ' 0%, ' + theLuckyColors.bottom + ' 100%)' 
          }); 
         } 
         else if(isFF) { 
          TweenLite.set(el, { 
           backgroundImage:'-moz-radial-gradient(center,circle cover,' + theLuckyColors.top + ' 0%, ' + theLuckyColors.bottom + ' 100%)' 
          }); 
         } 
         else { 
          TweenLite.set(el, { 
           backgroundImage:'radial-gradient(circle,' + theLuckyColors.top + ', ' + theLuckyColors.bottom + ')', 
           backgroundImage:'-webkit-radial-gradient(circle,' + theLuckyColors.top + ', ' + theLuckyColors.bottom + ')' 
          }); 
         } 
        } 
        swirl(); 
       } 
       ColorSwirl(['red','green','#4B0082','#9F00FF','yellow','orange'],'blue',.15); 
      } 

     }, 
     stopTheCycle: function() { 

     }, 

     render: function() { 
      return (
       <a className="psychedelicon" href={this.props.href} target={this.props.target} onMouseEnter={this.cycleColors} onMouseLeave={this.stopTheCycle}> 
        <i className={"fa fa-" + this.props.icon}></i> 
       </a> 
      ) 
     } 

    }); 
    module.exports = Psychedelicon; 

到目前爲止,我已經嘗試綁定「本」的元素接收事件:

onMouseEnter={this.cycleColors.bind(this)} 

和我:''你要綁定組件的方法到組件。 React以高性能的方式自動執行此操作,因此您可以安全地刪除此調用。

我也試過:

onMouseEnter={this.cycleColors.call(Psychedelicon)} 

和 OnMouseEnter在= {this.cycleColors.bind(Psychedelicon)}

這兩者產生的任何錯誤,但沒有奏效

我知道,功能否則工作,因爲當我改變時

onUpdateParams:[this] 

onUpdateParams:['.psychedelicon'] 

組件產生期望的行爲,不同之處在於它的影響都在同一時間的成分(我需要避免因此需要使用「這」)的。

我必須缺少一些東西。任何幫助表示讚賞。

+0

你的第二個代碼段也不起作用http://jsfiddle.net/arunpjohny/ssogpue2/1/ –

+0

@ArunPJohny嗯......你說的對,我把它刪除 – HelloWorld

+0

嘗試'$('#foo')。單擊(Module.addClass)'!在你的html代碼片段中,你甚至不會調用*方法。 – Bergi

回答

1

所以我能解決我自己的問題。這裏是沒有的伎倆代碼:

var React = require('react'); 
var GSAP = require('gsap'); 
var $  = require('jquery') 

var Psychedelicon = React.createClass({ 

    componentDidMount: function() { 

     var that = React.findDOMNode(this.refs.psicon); 
     $(that).hover(function() { 
    //detect device type for Psychedelicon 
      var touchPlatforms = ['iPhone', 'iPad', 'iPod', 'Android', 'Linux armv7l', 'WinCE']; 
         isTouch = false; 
         iDevice = false; 
         isDroid = false; 
         plat = navigator.platform; 

      if(plat === 'iPhone' || plat === 'iPad' || plat === 'iPod') { 
       isTouch = true; 
       iDevice = true; 
      } 
      else if (plat === 'Linux armv7l' || plat === 'Android') { 
       isTouch = true; 
       isDroid = true; 
      } 
      else { 
       for (var i = 0; i < touchPlatforms.length; i++) { 
        if (plat === touchPlatforms[i]) { 
         isTouch = true; 
         break; 
        } 
        else { 
         isTouch = false; 
        } 
       } 
      } 

    //sniff the for ie 
      var isIE = false 
       if (navigator.userAgent.toLowerCase().indexOf('msie') > -1 || navigator.userAgent.toLowerCase().indexOf('trident') > -1) { 
       isIE = true 
      } 

    //sniff for firefox 
      var isFF = false 
       if (navigator.userAgent.toLowerCase().indexOf('firefox') != -1) { 
       isFF = true 
      } 


    //Begin ColorSwirl on non-touch devices 
      if(!isTouch) { 
    //Define the Color Sets 
       var ColorSwirl = function(colorSet,defaultColor,time) { 
    //Pick random color. If the color is the same as the previous one pick blue instead. 
        var storedResult; 
        var randomColor = function(theArray) { 
         var result = theArray[Math.floor(Math.random() * (theArray.length))]; 
         if(result === storedResult){ 
          return(defaultColor)       
         } 
         else { 
          storedResult = result; 
          return(result) 
         } 
        } 
    //Pick our colors for the initial state 
        var theLuckyColors = {top:randomColor(colorSet),bottom:randomColor(colorSet)}; 
    //Start swirling 
        $(that).addClass('swirling'); 
        var swirl = function(){ 
         if($(that).hasClass('swirling')) { 
          TweenLite.to(theLuckyColors, time, {colorProps:{top:randomColor(colorSet), bottom:randomColor(colorSet)}, onUpdate:colorize, onUpdateParams:[that],onComplete:swirl}); 
         } 
        } 
    //Detect Browser and Pass Psychedelicon the appropriate radial gradients 
        var colorize = function(el) { 
         if(isIE) { 
          TweenLite.set(el, { 
           backgroundImage:'-ms-radial-gradient(center,circle cover,' + theLuckyColors.top + ' 0%, ' + theLuckyColors.bottom + ' 100%)' 
          }); 
         } 
         else if(isFF) { 
          TweenLite.set(el, { 
           backgroundImage:'-moz-radial-gradient(center,circle cover,' + theLuckyColors.top + ' 0%, ' + theLuckyColors.bottom + ' 100%)' 
          }); 
         } 
         else { 
          TweenLite.set(el, { 
           backgroundImage:'radial-gradient(circle,' + theLuckyColors.top + ', ' + theLuckyColors.bottom + ')', 
           backgroundImage:'-webkit-radial-gradient(circle,' + theLuckyColors.top + ', ' + theLuckyColors.bottom + ')' 
          }); 
         } 
        } 
        swirl(); 
       } 
       ColorSwirl(['red','green','#4B0082','#9F00FF','yellow','orange'],'blue',.15); 
      } 

     },function() { 
      var theLuckyColors = {top:'#FFFFFF',bottom:'#FFFFFF'}; 
      var stopNow = function(time){ 
       $(that).removeClass('swirling'); 
       TweenLite.to(theLuckyColors, time, {colorProps:{top:'#FFFFFF', bottom:'#FFFFFF'}, onUpdate:whiteWash, onUpdateParams:[that]}); 
      } 
      var whiteWash = function(el) { 
        TweenLite.set(el, { 
         backgroundImage:'-ms-radial-gradient(center,circle cover,#FFFFFF 0%, #FFFFFF 100%)', 
         backgroundImage:'-moz-radial-gradient(center,circle cover,#FFFFFF 0%, #FFFFFF 100%)', 
         backgroundImage:'radial-gradient(circle,#FFFFFF,#FFFFFF)', 
         backgroundImage:'-webkit-radial-gradient(circle,#FFFFFF,#FFFFFF)' 
        }); 
      } 
      stopNow(.15);  
     }); 
    }, 
    render: function() { 
     return (
      <a className="psychedelicon" ref="psicon" href={this.props.href} target={this.props.target} onMouseEnter={this.cycleColors} onMouseLeave={this.stopTheCycle}> 
       <i className={"fa fa-" + this.props.icon}></i> 
      </a> 
     ) 
    } 

}) 

module.exports = Psychedelicon; 

這裏是我從問題到解決方案有:

當我無法用「呼」地產生的結果是由@建議亞歷山大奧馬拉,我需要jQuery來加快測試和添加的可變

var that = $(this) 

到組件的最外層的範圍內,這樣我可以從內功能範圍訪問該組件本身像這樣:

//Note that onUpdateParams now references "that" which is equal to "this" in the scope of the actual component. 
TweenLite.to(theLuckyColors, time, {colorProps:{top:randomColor(colorSet), bottom:randomColor(colorSet)}, onUpdate:colorize, onUpdateParams:[that],onComplete:swirl}); 

這再次失敗,所以我將「this」的值記錄到控制檯,並看到我實際上引用了組件的構造函數而不是渲染的輸出!

我再次看過docs,看到我可以通過使用名爲「refs」的reactjs屬性來引用每個渲染實例上的渲染輸出。我只需要給渲染元素的「裁判」屬性:

render: function() { 
     return (
      <a className="psychedelicon" ref="psicon" href={this.props.href} target={this.props.target} onMouseEnter={this.cycleColors} onMouseLeave={this.stopTheCycle}> 
       <i className={"fa fa-" + this.props.icon}></i> 
      </a> 
     ) 
    } 

並引用裁判在我的方法,我決定跑出去「componentDidMount」代替。

var that = React.findDOMNode(this.refs.psicon); 

現在,每次我引用「」我是引用所呈現的元素本身(漂亮觀賞壯麗考慮它的重新渲染每0.15秒鼠標懸停),一切都桃色!

1

更新:這個答案不適用於React,但是是回答了一個更一般的以前版本的問題。


這看起來像另有說法爲不使用onclick屬性,但你可以使用callapply方法,並通過this作爲第一個參數。

<div id="foo" onClick="Module.addClass.call(this)"></div> 

但是,您可能要考慮使用addEventListener或jQuery的事件委派代替。

+0

對,但我使用React,所以內聯是我想要的方式...我會試試 – HelloWorld

+0

感謝您的幫助,但這不起作用。我已經更新了這個問題,並且爲了清晰起見添加了整個組件的代碼。 – HelloWorld

+0

好的,我解決了這個問題。由於我描述的問題,React有一種訪問被稱爲refs的渲染元素的方法。我能夠使用它來引用呈現的元素。上面的代碼失敗了,因爲「this」引用了組件的constructer而不是渲染的元素。 – HelloWorld

相關問題