use resize observer to check textarea size (#13295)

fix: #10151
This commit is contained in:
zombieJ 2018-11-27 13:46:42 +08:00 committed by GitHub
parent df49b767b1
commit 8d1d595d76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 107 additions and 7 deletions

View File

@ -1,6 +1,8 @@
import * as React from 'react';
import omit from 'omit.js';
import classNames from 'classnames';
import { polyfill } from 'react-lifecycles-compat';
import ResizeObserver from 'resize-observer-polyfill';
import calculateNodeHeight from './calculateNodeHeight';
function onNextFrame(cb: () => void) {
@ -35,12 +37,13 @@ export interface TextAreaState {
textareaStyles?: React.CSSProperties;
}
export default class TextArea extends React.Component<TextAreaProps, TextAreaState> {
class TextArea extends React.Component<TextAreaProps, TextAreaState> {
static defaultProps = {
prefixCls: 'ant-input',
};
nextFrameActionId: number;
resizeObserver: ResizeObserver | null;
state = {
textareaStyles: {},
@ -50,15 +53,40 @@ export default class TextArea extends React.Component<TextAreaProps, TextAreaSta
componentDidMount() {
this.resizeTextarea();
this.updateResizeObserverHook();
}
componentWillReceiveProps(nextProps: TextAreaProps) {
componentDidUpdate(prevProps: TextAreaProps) {
// Re-render with the new content then recalculate the height as required.
if (this.props.value !== nextProps.value) {
if (this.nextFrameActionId) {
clearNextFrameAction(this.nextFrameActionId);
}
this.nextFrameActionId = onNextFrame(this.resizeTextarea);
if (prevProps.value !== this.props.value) {
this.resizeOnNextFrame();
}
this.updateResizeObserverHook();
}
componentWillUnmount() {
if (this.resizeObserver) {
this.resizeObserver.disconnect();
}
}
resizeOnNextFrame = () => {
if (this.nextFrameActionId) {
clearNextFrameAction(this.nextFrameActionId);
}
this.nextFrameActionId = onNextFrame(this.resizeTextarea);
}
// We will update hooks if `autosize` prop change
updateResizeObserverHook() {
if (!this.resizeObserver && this.props.autosize) {
// Add resize observer
this.resizeObserver = new ResizeObserver(this.resizeOnNextFrame);
this.resizeObserver.observe(this.textAreaRef);
} else if (this.resizeObserver && !this.props.autosize) {
// Remove resize observer
this.resizeObserver.disconnect();
this.resizeObserver = null;
}
}
@ -140,3 +168,7 @@ export default class TextArea extends React.Component<TextAreaProps, TextAreaSta
);
}
}
polyfill(TextArea);
export default TextArea;

View File

@ -1032,6 +1032,28 @@ exports[`renders ./components/input/demo/textarea.md correctly 1`] = `
/>
`;
exports[`renders ./components/input/demo/textarea-resize.md correctly 1`] = `
<div>
<button
class="ant-btn"
type="button"
>
<span>
Auto Resize:
</span>
<span>
false
</span>
</button>
<textarea
class="ant-input"
rows="4"
>
autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。ending
</textarea>
</div>
`;
exports[`renders ./components/input/demo/tooltip.md correctly 1`] = `
<input
class="ant-input"

View File

@ -0,0 +1,45 @@
---
order: 99
title:
zh-CN: 文本域
en-US: TextArea
debug: true
---
## zh-CN
用于多行输入。
## en-US
For multi-line input.
````jsx
import { Input, Button } from 'antd';
const { TextArea } = Input;
const defaultValue = 'autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。ending';
class Demo extends React.Component {
state = {
autoResize: false,
}
render() {
const { autoResize } = this.state;
return (
<div>
<Button onClick={() => this.setState({ autoResize: !autoResize })}>
Auto Resize: {String(autoResize)}
</Button>
<TextArea rows={4} autosize={autoResize} defaultValue={defaultValue} />
</div>
);
}
}
ReactDOM.render(<Demo />, mountNode);
````

View File

@ -87,6 +87,7 @@
"react-lazy-load": "^3.0.13",
"react-lifecycles-compat": "^3.0.4",
"react-slick": "~0.23.2",
"resize-observer-polyfill": "^1.5.0",
"shallowequal": "^1.1.0",
"warning": "~4.0.2"
},