Browse Source

use resize observer to check textarea size (#13295)

fix: #10151
pull/13311/head
zombieJ 6 years ago
committed by GitHub
parent
commit
8d1d595d76
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 46
      components/input/TextArea.tsx
  2. 22
      components/input/__tests__/__snapshots__/demo.test.js.snap
  3. 45
      components/input/demo/textarea-resize.md
  4. 1
      package.json

46
components/input/TextArea.tsx

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

22
components/input/__tests__/__snapshots__/demo.test.js.snap

@ -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`] = ` exports[`renders ./components/input/demo/tooltip.md correctly 1`] = `
<input <input
class="ant-input" class="ant-input"

45
components/input/demo/textarea-resize.md

@ -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);
````

1
package.json

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

Loading…
Cancel
Save