开始
在低版本 Angular 使用中,我这里目前使用的 Angular6.x 版本先看问题所在。
想做一个通用的图片上传,我们要使用双向绑定图片路径,那么就会使用 [(imgUrl)] 来进行双向绑定
<input type="file" [(imgUrl)]="imgUrl">
问题
在正常封装的组件,我们在组件开发,这里一切都没问题
import {Input,EventEmitter} from '@angular/core';
@Input()
public imgUrl: string;
// 用于双向绑定
public imgUrlChange: EventEmitter<string> = new EventEmitter();
constructor(){
this.imgUrl = '修改的图片链接';
// 此处问题,一切都很正常的双向绑定
this.imgUrlChange.emit(this.imgUrl);
}
但是你一旦使用了第三方的上传工具,比如 Layui 的 upload,还有其他,只要使用后有回调的那么双向绑定就会失效,例如
import {Input,EventEmitter} from '@angular/core';
@Input()
public imgUrl: string;
// 用于双向绑定
public imgUrlChange: EventEmitter<string> = new EventEmitter();
constructor(){
this.imgUrl = '修改的图片链接';
// 此处问题,一切都很正常的双向绑定
this.imgUrlChange.emit(this.imgUrl);
layui.upload.render({
elem: '#upload',
url: '填写你的后端上传请求地址',
done: (res) => {
// 拿到请求上传成功后的图片地址,然后双向绑定
this.imgUrl = res.data;
// 这里就会失败,无法双向绑定成功,组件内数据改了,但是父组件没有被改变
this.imgUrlChange.emit(this.imgUrl);
}
})
}
解决办法
采用 NgZone,这个 API 没有被 Angulars zone 打补丁。需要明确地使代码在 Angulars 区域中运行,以便之后发生更改检测:
import {Input,EventEmitter,NgZone} from '@angular/core';
@Input()
public imgUrl: string;
// 用于双向绑定
public imgUrlChange: EventEmitter<string> = new EventEmitter();
constructor(private zone: NgZone){
this.imgUrl = '修改的图片链接';
// 此处问题,一切都很正常的双向绑定
this.imgUrlChange.emit(this.imgUrl);
layui.upload.render({
elem: '#upload',
url: '填写你的后端上传请求地址',
done: (res) => {
// 拿到请求上传成功后的图片地址,然后双向绑定
this.imgUrl = res.data;
// 这里使用 zone
this.zone.run(() => {
// 此时双向绑定一切正常,父组件子组件都同步值
this.imgUrlChange.emit(this.imgUrl);
})
}
})
}