Javascript “的范围”;这";在module.exports中
我正在使用module.exports将React.js组件转换为Common.js模块,并且在从组件元素的方法之一访问组件元素上下文中的“this”时遇到问题 下面是整个组件。我在出现问题的那一行上方放置了一条注释。起初我确实尝试了一个不太详细的例子,但我认为这不足以解释这个问题Javascript “的范围”;这";在module.exports中,javascript,reactjs,commonjs,node-modules,Javascript,Reactjs,Commonjs,Node Modules,我正在使用module.exports将React.js组件转换为Common.js模块,并且在从组件元素的方法之一访问组件元素上下文中的“this”时遇到问题 下面是整个组件。我在出现问题的那一行上方放置了一条注释。起初我确实尝试了一个不太详细的例子,但我认为这不足以解释这个问题 var React = require('react'); var GSAP = require('gsap'); var Psychedelicon = React.createClas
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;
我得到:``您正在将组件方法绑定到组件。React以高性能方式自动为您执行此操作,因此您可以安全地删除此呼叫。”
我还尝试:
onMouseEnter={this.cycleColors.call(Psychedelicon)}
及
onMouseCenter={this.cycleColors.bind(迷幻药)}
这两种方法都没有产生错误,但都不起作用
我知道该函数在其他情况下有效,因为当我更改
onUpdateParams:[this]
到
组件会产生所需的行为,除了它会同时影响所有组件(我需要避免,因此需要使用“this”)
我一定错过了什么。非常感谢您的帮助。更新:此答案不适用于React,而是针对问题的更一般的先前版本做出的回答
这看起来像是不使用
onclick
属性的另一个参数,但是您可以使用call
或apply
方法,并将This
作为第一个参数传递
<div id="foo" onClick="Module.addClass.call(this)"></div>
但是,您可能需要考虑使用<代码> AdvestTristAudio/Cuth>或jQuery的事件委派代替。
所以我能够解决我自己的问题。下面是实现此技巧的代码:
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;
到组件的最外层作用域,这样我就可以从内部函数的作用域访问组件本身,如下所示:
//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”的值记录到控制台,并看到我实际上引用的是组件的构造函数,而不是呈现的输出
我又看了一遍,发现我可以通过使用名为“refs”的reactjs属性在每个渲染实例上引用渲染输出。我只需要给渲染元素一个“ref”属性:
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>
)
}
现在,每次我引用“that”时,我引用的是渲染元素本身(考虑到它在鼠标上每隔.15秒重新渲染一次,所以非常不精确),而且一切都很美好 你的第二个片段也不起作用@ArunPJohny嗯。。。你说得对,我删除了itTry
$('#foo')。单击(Module.addClass)
!在您的html代码片段中,您甚至没有调用该方法。对,但我使用的是React,所以内联是一种方式,我想。。。我会尝试一下,谢谢你的帮助,但那是行不通的。为了清晰起见,我已经更新了问题并添加了整个组件的代码。好的,我解决了这个问题。由于我描述的问题,React有一种访问渲染元素refs的方法。我能够使用它来引用渲染的元素。上面的代码失败,因为“this”引用的是组件的构造函数而不是呈现的元素。@HelloWorld您应该将您的解决方案作为答案发布,我将对此进行投票。好的,我发布了答案,并提供了一些细节,以防有人处理相同的问题。如果允许的话,我会在12小时内接受我自己的答案。
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});
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>
)
}
var that = React.findDOMNode(this.refs.psicon);