Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/465.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript React.js ES6避免绑定';这';每种方法_Javascript_Reactjs_Ecmascript 6 - Fatal编程技术网

Javascript React.js ES6避免绑定';这';每种方法

Javascript React.js ES6避免绑定';这';每种方法,javascript,reactjs,ecmascript-6,Javascript,Reactjs,Ecmascript 6,最近,我开始修补React.js,我喜欢它。我从普通的ES5开始,为了掌握窍门,所有的文档都是用ES5编写的 但现在我想试试ES6,因为它光鲜亮丽,而且看起来确实简化了一些事情。让我非常困扰的是,对于我添加到组件类中的每个方法,我现在都必须将“this”绑定到,否则它就无法工作。因此,我的构造函数最终看起来是这样的: constructor(props) { super(props); this.state = { ...some initial state... } this.s

最近,我开始修补React.js,我喜欢它。我从普通的ES5开始,为了掌握窍门,所有的文档都是用ES5编写的

但现在我想试试ES6,因为它光鲜亮丽,而且看起来确实简化了一些事情。让我非常困扰的是,对于我添加到组件类中的每个方法,我现在都必须将“this”绑定到,否则它就无法工作。因此,我的构造函数最终看起来是这样的:

constructor(props) {
  super(props);
  this.state = { ...some initial state... }

  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
}
// common function:
function bind(self,methods){
     for(var key in methods){
       self[key] = methods[key].bind(self);
     }
}

// your class:
class MyClass {
     constructor() {
          bind(this,{
              someHandler1(event){ 
                //... 
              },
              someHandler2(event){ 
                //...
              }
          })
     }
}
如果我在我的类中添加更多的方法,这将是一个更大、更丑陋的烂摊子

我的问题是,有没有办法绕过这个问题,或者至少让它更简单、更短、更不难看?我想尝试使用ES6进行React的一个主要原因是使我的代码更简洁,但这恰恰相反。如果您有任何建议或意见,我们将不胜感激。

您可以使用它在构造函数之外进行绑定。它们看起来如下所示:

class Foo extends React.Component {

  handleBar = () => {
    console.log('neat');
  };

  handleFoo = () => {
    console.log('cool');
  };

  render() {
    return (
      <div
        onClick={this.handleBar}
        onMouseOver={this.handleFoo}
      />
    );
  }

}
类Foo扩展了React.Component{
车把=()=>{
console.log('neat');
};
handleFoo=()=>{
console.log('cool');
};
render(){
返回(
);
}
}
Babel通过its实验性地支持类字段,但它们仍然是“实验性”的,因为它们是a(尚未在Babel预设中)


但是,在ES7或在Babel中启用该功能之前,您需要手动进行绑定。巴贝尔在的博客文章中简要介绍了这一主题。

艾伦的建议很好,但如果你想要另一种方式,有:

    class AppCtrlRender extends Component {
        binder(...methods) { methods.forEach( (method) => this[method] = this[method].bind(this) ); }

        render() {
            var isMobile = this.state.appData.isMobile;
            var messages = this.state.appData.messages;
            return (
                <div id='AppCtrlSty' style={AppCtrlSty}>
                    React 1.3 Slider
                    <br/><br/>
                    <div className='FlexBoxWrap'>
                        <Slider isMobile={isMobile}/>
                        <JList data={messages}/>
                    </div>
                </div>
            );
        }
    }

    var getAppState = function() {
        return {
            appData: AppStore.getAppData()
        };
    };

    export default class AppCtrl extends AppCtrlRender {
        constructor() {
            super();
            this.state = getAppState();
            this.binder('appStoreDidChange');
        }

        componentDidMount() {
            var navPlatform = window.navigator.platform;
            Actions.setWindowDefaults(navPlatform);
        }
        componentWillMount() { AppStore.onAny(this.appStoreDidChange); }
        componentWillUnmount() { AppStore.offAny(this.appStoreDidChange); }
        appStoreDidChange() { this.setState(getAppState()); }
    }
类AppCtrlRender扩展组件{
binder(…methods){methods.forEach((method)=>this[method]=this[method].bind(this));}
render(){
var isMobile=this.state.appData.isMobile;
var messages=this.state.appData.messages;
返回(
反应1.3滑块


); } } var getAppState=函数(){ 返回{ appData:AppStore.getAppData() }; }; 导出默认类AppCtrl扩展AppCtrlRender{ 构造函数(){ 超级(); this.state=getAppState(); 此.binder('appStoreDidChange'); } componentDidMount(){ var navPlatform=window.navigator.platform; Actions.setWindowDefault(导航平台); } componentWillMount(){AppStore.onAny(this.appStoreDidChange);} componentWillUnmount(){AppStore.offAny(this.appStoreDidChange);} appStoreDidChange(){this.setState(getAppState());} }

您可以将任意数量的方法添加到此.binder('method1','method2',…)

另一种选择是使用装饰器。您在原型上声明了一个getter,并且在第一次访问实例时,它使用该函数的绑定版本定义了自己的属性

但是有一个陷阱!在开发过程中,它不会取代属性,它会绑定到每个访问这意味着您不会破坏react hot loader。至少对我来说,这很重要

我创建了一个库,它提供了这一点

import {bound} from 'class-bind';

class App {
  constructor(){
    this.foo = 'bar';
  }

  @bound
  returnsFoo(){
    return this.foo;
  }

  render(){
    var returnsFoo = this.returnsFoo;
    return (
      <div>
        {returnsFoo()} === 'bar'
      </div>
    );
  }
}

如果使用
stage-0
,则存在函数绑定语法

class MyComp extends Component {

  handleClick() { console.log('doing things') }

  render() {
    return <button onClick={::this.handleClick}>Do Things</button>
  }

}
类MyComp扩展组件{
handleClick(){console.log('doing things')}
render(){
回报
}
}
这会将结构分解为This.handleClick.call(This),我认为这通常已经足够了。

一个避免绑定的方法

class MyComp extends Component {

  render() {
    return <button onClick={e => this.handleClick(e)}>Do Things</button>
  }

}
类MyComp扩展组件{
render(){
返回这个。handleClick(e)}>做事情
}
}
免责声明:未经测试也无法轻松处理多个参数(在本例中,只有一个,事件(e))

此外,根据这篇可能值得一读的文章,这个答案可能是不应该做什么的一个例子:


实际上,我更喜欢通过将父上下文传递给子对象来模拟OOP继承

class Parent extends Component {
  state = {happy: false}

  changeState(happy) {
    this.setState({happy})
  }

  render() {
    return (
      <Child parent={this} >
    )
  }
}

class Child extends Component {
   //...
   this.props.parent.changeState(true)
}
类父级扩展组件{
state={happy:false}
改变状态(快乐){
this.setState({happy})
}
render(){
返回(
)
}
}
类子扩展组件{
//...
this.props.parent.changeState(true)
}
$0.02,
Jon

我创建了一个方法来组织所有的“绑定”


我使用一个helper函数
doBinding(this)
,我在每个构造函数中调用它。在本例中,它绑定
\u handleChange1()
\u handleChange2()

即使您不使用Babel,该方法也可以工作

我的处理程序方法都以
\u
开头(表示它们是私有的约定)。因此
doBinding()
查找
\u
。如果不使用此约定,可以删除
if(key.startsWith(“\u”)

function doBinding(obj) {
    const proto = Object.getPrototypeOf(obj);
    for (const key of Object.getOwnPropertyNames(proto)) {
        if (key.startsWith("_")) {
            obj[key] = obj[key].bind(obj);
        }
    }
}

使用一个公共函数执行如下绑定工作如何:

constructor(props) {
  super(props);
  this.state = { ...some initial state... }

  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
  this.someHandler = this.someHandler.bind(this);
}
// common function:
function bind(self,methods){
     for(var key in methods){
       self[key] = methods[key].bind(self);
     }
}

// your class:
class MyClass {
     constructor() {
          bind(this,{
              someHandler1(event){ 
                //... 
              },
              someHandler2(event){ 
                //...
              }
          })
     }
}

你真的在某处使用你所有的方法作为处理程序吗?这也是从一个更高级别的组件中获取的,所以是的,它们都在层次结构的某个地方使用。我试图遵循他们的理念,试图最好地弄清楚哪个组件需要知道什么,这就是我最终得到的结果。但不是(不应该)它们可以作为组件对象上的方法调用,而不是作为函数传递?我个人使用decorators()为了这个而不是类属性初始值设定项。谢谢。那太可惜了。我使用gulp作为我的构建系统,而gulp包似乎没有这个选项。关于如何让它更容易接受,有什么建议吗?哦,是的,你可以。我用
babel({stage:0})运行它
它成功了。这似乎是一个暂时的解决方案,因为它还处于早期阶段,但目前效果会很好。谢谢你的帮助。@Brandon它们也有同样的效果<
// common function:
function bind(self,methods){
     for(var key in methods){
       self[key] = methods[key].bind(self);
     }
}

// your class:
class MyClass {
     constructor() {
          bind(this,{
              someHandler1(event){ 
                //... 
              },
              someHandler2(event){ 
                //...
              }
          })
     }
}