Javascript React ES6功能范围声明

Javascript React ES6功能范围声明,javascript,reactjs,ecmascript-6,Javascript,Reactjs,Ecmascript 6,我环顾四周好几天了,似乎无法解决这个问题。我有一个表单可以通过XMLHTTPRequestUpload处理文件上传,我有一个onProgress回调,我想调用它并直观地更新UI中发生的事情,但我似乎无法从“onProgress”内部成功调用函数 我尝试使用console.log查找函数updateProgress的定义范围。”在上传文件的内部,onProgress调用是XMLHTTP请求本身。所以我尝试了“AddShow”,这个类本身。它不报告错误,并列出updateProgress是类的成员函

我环顾四周好几天了,似乎无法解决这个问题。我有一个表单可以通过XMLHTTPRequestUpload处理文件上传,我有一个onProgress回调,我想调用它并直观地更新UI中发生的事情,但我似乎无法从“onProgress”内部成功调用函数

我尝试使用console.log查找函数updateProgress的定义范围。”在上传文件的内部,onProgress调用是XMLHTTP请求本身。所以我尝试了“AddShow”,这个类本身。它不报告错误,并列出updateProgress是类的成员函数,但当尝试调用它时,我仍然得到

AddShow.updateProgress is not a function
    at XMLHttpRequestUpload.onProgress
沃尔多在哪里?如何调用我的函数

下面是我的整个React组件类:

export class AddShow extends React.Component {
  constructor(props) {
    super(props);

    this.handleTextChange = this.handleTextChange.bind(this);
    this.uploadFile = this.uploadFile.bind(this);
    this.updateProgress = this.updateProgress.bind(this);
  }

  // function that updates the state of the form input
  handleTextChange(evt) {
    this.props.dispatch(actions.changeShowTitleText(evt.target.value));
  }

  //function that show the progress of file upload
  updateProgress(progress) {
    progress = Math.floor(progress * 100);
    //call the dispatch actions to update redux state
    this.props.dispatch(actions.changeCompleteValue(progress));
    this.props.dispatch(actions.changeCompleteText(progress + '%'));
    this.props.dispatch(actions.changeCompleteARIA(progress + ' percent'));

    // this.props.complete = progress;
    // this.props.completeText = progress + '%';
    // this.props.ariaCompleteText = progress + ' percent';
  }

  // when 'add show' is pressed, validate form and upload
  onSubmit(e) {
    e.preventDefault();
    let titleText = this.props.showTitle;
    if (titleText < 1) {
      alert("Please provide a Show Title.");
    } else {
      // a title has been typed in, call upload with that info.
      this.uploadFile(titleText);
    }
  }

  //function that finally uploads the file given all the information
  uploadFile(title) {
    var uploader = new VimeoUpload({
      name: title,
      file: selectedFile,
      token: process.env.ACCESS_TOKEN,
      onProgress: function(data) {
        var percent = data.loaded / data.total;
        AddShow.updateProgress(percent);
      },
      onComplete: function(videoId, index) {
        var url = 'https://vimeo.com/' + videoId
      }
    });

    uploader.upload();
  }

  // set the global file variable if the input changes
  handleFileSelect(file) {
    console.log("These are the files retrieved", file.target.files[0]);
    selectedFile = file.target.files[0];
  }

  render() {
    var {dispatch, showTitle, complete, completeText, ariaCompleteText} = this.props;
    completeText = '0%';
    ariaCompleteText = "0 percent";

    return(
      <div className="row">
        <div className="column small-centered small-11 medium-8 large-6">
          <div className="container">
            <p>Drag the Video You Want to Upload to Screen</p>
            <form ref="form" onSubmit={this.onSubmit.bind(this)} className="add-show-form">
              <input type="file" placeholder="Select Video File" onChange={(evt) => this.handleFileSelect(evt)}/>
              <p ref="alertText"></p>
              <input type="text" value={this.props.showTitle} onChange={this.handleTextChange} placeholder="Show Title"/>
              <button className="button expanded">Add Show</button>
            </form>
            <div className="progress" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuetext={this.props.ariaCompleteText} aria-valuemax="100">
              <span className="progress-meter" style={{width: this.props.complete + '%'}}>
                <p className="progress-meter-text">{this.props.completeText}</p>
              </span>
            </div>
          </div>
        </div>
      </div>
    );
  }
};
导出类AddShow扩展了React.Component{
建造师(道具){
超级(道具);
this.handleTextChange=this.handleTextChange.bind(this);
this.uploadFile=this.uploadFile.bind(this);
this.updateProgress=this.updateProgress.bind(this);
}
//更新表单输入状态的函数
handleTextChange(evt){
this.props.dispatch(actions.changeShowtTitleText(evt.target.value));
}
//显示文件上载进度的函数
updateProgress(进度){
进度=数学楼层(进度*100);
//调用调度操作以更新redux状态
this.props.dispatch(actions.changeCompleteValue(progress));
this.props.dispatch(actions.changepletetext(progress+'%');
this.props.dispatch(actions.changeCompleteARIA(进度+百分比));
//this.props.complete=进度;
//this.props.completeText=进度+'%';
//this.props.ariapletext=进度+百分比;
}
//按下“添加显示”按钮时,验证表单并上载
提交(e){
e、 预防默认值();
让titleText=this.props.showTitle;
如果(titleText<1){
警告(“请提供节目名称”);
}否则{
//已键入标题,请使用该信息致电upload。
此.uploadFile(titleText);
}
}
//函数,在给定所有信息的情况下最终上载文件
上传文件(标题){
var上传器=新的VimeOutload({
姓名:职务,,
文件:选择文件,
令牌:process.env.ACCESS\u令牌,
onProgress:功能(数据){
变量百分比=data.loaded/data.total;
AddShow.updateProgress(百分比);
},
onComplete:函数(videoId,索引){
var url='1〕https://vimeo.com/“+videoId
}
});
uploader.upload();
}
//如果输入发生更改,请设置全局文件变量
handleFileSelect(文件){
log(“这些是检索到的文件”,file.target.files[0]);
selectedFile=file.target.files[0];
}
render(){
var{dispatch,showttitle,complete,completeText,ariaCompleteText}=this.props;
completeText='0%';
ariaCompleteText=“0%”;
返回(
将要上载的视频拖到屏幕上

this.handleFileSelect(evt)}/>

添加显示

{this.props.completeText}

); } };
对您来说,最简单的解决方案是只使用一个箭头函数,该函数具有词法作用域,并将作用域限定为
上传文件的上下文:

uploadFile(title) {
  var uploader = new VimeoUpload({
    // ...
    onProgress: (data) => { // <-- use arrow function
      var percent = data.loaded / data.total;
      this.updateProgress(percent);
    }
  // ...
}

请注意这一行

AddShow.updateProgress(percent);
尝试访问函数本身的
updateProgress
,而不是没有此方法的原型


如果您想以这样的静态方式调用函数,您需要在原型上调用它。

解决方案1:使用静态方法

static updateProgress(进度){
进度=数学楼层(进度*100);
//调用调度操作以更新redux状态
this.props.dispatch(actions.changeCompleteValue(progress));
this.props.dispatch(actions.changepletetext(progress+'%');
this.props.dispatch(actions.changeCompleteARIA(进度+百分比));

}
您需要在onProgress回调的新范围内维护对外部范围(即外部范围)的引用。传统的(ES5)方法是在变量(通常称为self)中创建对它的引用,然后使用该引用在回调中调用该方法:

  uploadFile(title) {
    // self now references the outer this
    var self = this;
    var uploader = new VimeoUpload({
      name: title,
      file: selectedFile,
      token: process.env.ACCESS_TOKEN,
      onProgress: function(data) {
        var percent = data.loaded / data.total;

        // we can access the outer scope on self here
        self.updateProgress(percent);
      },
      onComplete: function(videoId, index) {
        var url = 'https://vimeo.com/' + videoId
      }
    });

    uploader.upload();
  }
假设您在代码中使用类,我假设您乐于使用ES6代码,因此实现相同效果的更优雅的方法是使用lambda(或fat arrow)函数。这意味着使用以下语法声明函数:

const someFunction = (anArgument) => {
    return aResult;
}
这(大致)相当于:

function someFunction(anArgument) {
    return aResult;
}
不同之处在于,使用lambda语法声明函数时,不会创建新的作用域。实际上,函数内部的
与函数外部的
相同。然后,我们可以将uploadFile处理程序编写为:

  uploadFile(title) {
    var uploader = new VimeoUpload({
      name: title,
      file: selectedFile,
      token: process.env.ACCESS_TOKEN,
      onProgress: (data) => {
        var percent = data.loaded / data.total;
        this.updateProgress(percent);
      },
      onComplete: (videoId, index) => {
        var url = 'https://vimeo.com/' + videoId
      }
    });

    uploader.upload();
  }

嗯,试试这个,使用
onProgress:(data)=>{
并将
AddShow.updateProgress(百分比);
更改为
this.updateProgress(百分比),将匿名方法更改为箭头函数来绑定实例
然后请评论您遇到的错误(如果有)。
AddShow.updateProgress
无法工作,因为
updateProgress
AddShow
实例的一种方法。谢谢,这非常有效。我正在将旧语法转换为新的ES6语法,以更接近文档,我想我错过了这一点。“不同之处在于,当您使用lambda语法声明函数时,不会创建新的作用域。”这是不正确的。
与作用域不同。每个函数调用都会创建一个新的作用域。但是,对于箭头函数,作用域没有自己的
值。
  uploadFile(title) {
    var uploader = new VimeoUpload({
      name: title,
      file: selectedFile,
      token: process.env.ACCESS_TOKEN,
      onProgress: (data) => {
        var percent = data.loaded / data.total;
        this.updateProgress(percent);
      },
      onComplete: (videoId, index) => {
        var url = 'https://vimeo.com/' + videoId
      }
    });

    uploader.upload();
  }