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