【发布时间】:2019-01-14 09:08:09
【问题描述】:
问题:
我正在尝试从react-cropper 中创建一个在 TypeScript 中工作的示例。该示例适用于 .JSX,并且有 Typings,所以我认为它可以很好地工作,对 .JSX 代码进行一些更改。
让我印象深刻的一件棘手的事情是 TypeScript 和 React 中的参考模式。但是,我发现了这个惊人的 question on SO,我已经按照它来设置所有内容。
预期:
ref-pattern 将按预期工作,并且我可以访问底层函数(从对象)。
即我希望看到this.cropRef 可以访问getCroppedCanvas(在react-cropper 中定义)。
实际:
cropImage() 函数中的console.log(this) 显示refs 为空,即使我按照上面的示例进行操作。
尝试使用现在已弃用的使用字符串的引用模式告诉我this 具有指向cropImage() 函数的引用标题。但是,由于 TS 是强类型的,我无权访问getCroppedCanvas()。
代码:
import * as React from "react";
import Cropper from 'react-cropper';
import 'cropperjs/dist/cropper.css';
export class ImageEditor extends React.Component<any, any> {
private cropRef : React.RefObject<Cropper>;
constructor(props : any) {
super(props);
this.state = {
src : "",
cropResult : ""
};
this.cropRef = React.createRef();
this.cropImage = this.cropImage.bind(this);
this.onChange = this.onChange.bind(this);
}
onChange(e : any) {
e.preventDefault();
let files;
if (e.dataTransfer) {
files = e.dataTransfer.files;
} else if (e.target) {
files = e.target.files;
}
const reader = new FileReader();
reader.onload = () => {
this.setState({ src : reader.result });
};
reader.readAsDataURL(files[0]);
}
cropImage() {
console.log(this.refs);
if (typeof this.cropRef.current.getCroppedCanvas() === 'undefined') {
return;
}
this.setState({
cropResult: this.cropRef.current.getCroppedCanvas().toDataURL(),
});
}
render() {
return (
<div>
<div style={{ width: '100%' }}>
<input type="file" onChange={this.onChange} />
<br />
<br />
<Cropper
style={{ height: 400, width: '100%' }}
aspectRatio={16 / 9}
preview=".img-preview"
guides={false}
src={this.state.src}
ref={(cropper : any) => { this.cropRef = cropper}}
/>
</div>
<div>
<div className="box" style={{ width: '50%', float: 'right' }}>
<h1>Preview</h1>
<div className="img-preview" style={{ width: '100%', float: 'left', height: 300 }} />
</div>
<div className="box" style={{ width: '50%', float: 'right' }}>
<h1>
<span>Crop</span>
<button onClick={this.cropImage} style={{ float: 'right' }}>
Crop Image
</button>
</h1>
<img style={{ width: '100%' }} src={this.state.cropResult} alt="cropped image" />
</div>
</div>
</div>
);
}
}
编辑:
为 react-cropper 编辑了 index.d.ts:
import * as cropperjs from 'cropperjs';
import * as React from 'react';
import Data = cropperjs.Data;
import ContainerData = cropperjs.ContainerData;
import ImageData = cropperjs.ImageData;
import CanvasData = cropperjs.CanvasData;
import CropBoxData = cropperjs.CropBoxData;
import CroppedCanvasOptions = cropperjs.CroppedCanvasOptions;
type ReactCropperProps = cropperjs.CropperOptions & React.AllHTMLAttributes<HTMLImageElement>;
interface ReactCropper extends cropperjs {} // tslint:disable-line no-empty-interface
declare class ReactCropper extends React.Component<ReactCropperProps> {
on(eventname: string, callback: () => void): void;
}
export default ReactCropper;
package.json
{
"name": "name",
"version": "1.0.0",
"description": "packages for content",
"main": "webpack.config.js",
"scripts": {
"build": "webpack",
"test": "karma start karma.unit.build.js",
"build-test": "karma start karma.unit.js",
"coverage": "karma start karma.coverage.js"
},
"author": "Joakim Bajoul Kakaei",
"license": "ISC",
"devDependencies": {
"@types/chai": "^4.1.4",
"@types/mocha": "^5.2.5",
"@types/react": "^16.4.7",
"@types/react-cropper": "./node_modules/react-cropper.fixed",
"@types/react-dom": "^16.0.6",
"@types/react-dropzone": "^4.2.0",
"@types/sinon": "^5.0.1",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"chai": "^4.1.2",
"css-loader": "^1.0.0",
"istanbul-instrumenter-loader": "^3.0.1",
"karma": "^2.0.5",
"karma-chai": "^0.1.0",
"karma-coverage": "^1.1.2",
"karma-mocha": "^1.3.0",
"karma-phantomjs-launcher": "^1.0.4",
"karma-sinon": "^1.0.5",
"karma-typescript-preprocessor2": "^1.2.1",
"karma-webpack": "^3.0.0",
"mocha": "^5.2.0",
"mocha-webpack": "^1.1.0",
"phantomjs-prebuilt": "^2.1.16",
"sinon": "^6.1.4",
"style-loader": "^0.21.0",
"ts-loader": "^4.4.2",
"ts-node": "^7.0.0",
"typescript": "^2.9.2",
"typings": "^2.1.1",
"webpack": "^4.16.2",
"webpack-cli": "^3.1.0"
},
"dependencies": {
"npm": "^6.3.0",
"react": "^16.4.1",
"react-cropper": "^1.0.1",
"react-dom": "^16.4.1",
"react-dropzone": "^4.2.13"
}
}
node_modules/react-cropper/package.json:
{
"name": "@types/react-cropper",
"dependencies": {
}
}
【问题讨论】:
标签: javascript reactjs typescript