<script> import omit from 'omit.js' import inputProps from './inputProps' import calculateNodeHeight from './calculateNodeHeight' function onNextFrame (cb) { if (window.requestAnimationFrame) { return window.requestAnimationFrame(cb) } return window.setTimeout(cb, 1) } function clearNextFrameAction (nextFrameId) { if (window.cancelAnimationFrame) { window.cancelAnimationFrame(nextFrameId) } else { window.clearTimeout(nextFrameId) } } function fixControlledValue (value) { if (typeof value === 'undefined' || value === null) { return '' } return value } export default { name: 'TextArea', props: { ...inputProps, autosize: [Object, Boolean], }, model: { prop: 'value', event: 'change.value', }, data () { const { value, defaultValue } = this.$props return { stateValue: fixControlledValue(value === undefined ? defaultValue : value), nextFrameActionId: undefined, textareaStyles: {}, } }, computed: { }, watch: { value (val) { this.stateValue = fixControlledValue(val) if (this.nextFrameActionId) { clearNextFrameAction(this.nextFrameActionId) } this.nextFrameActionId = onNextFrame(this.resizeTextarea) }, }, mounted () { this.resizeTextarea() }, methods: { handleKeyDown (e) { if (e.keyCode === 13) { this.$emit('pressEnter', e) } this.$emit('keydown', e) }, resizeTextarea () { const { autosize } = this.$props if (!autosize || !this.$refs.textArea) { return } const minRows = autosize ? autosize.minRows : null const maxRows = autosize ? autosize.maxRows : null const textareaStyles = calculateNodeHeight(this.$refs.textArea, false, minRows, maxRows) this.textareaStyles = textareaStyles }, getTextAreaClassName () { const { prefixCls, disabled } = this.$props return { [prefixCls]: true, [`${prefixCls}-disabled`]: disabled, } }, handleTextareaChange (e) { const { value } = this.$props if (value === undefined) { this.stateValue = e.target.value this.$nextTick(() => { this.resizeTextarea() }) } else { this.$forceUpdate() this.$emit('change.value', e.target.value) this.$emit('change', e) } }, focus () { this.$refs.textArea.focus() }, blur () { this.$refs.textArea.blur() }, }, render () { const { stateValue, getTextAreaClassName, handleKeyDown, handleTextareaChange, textareaStyles } = this const otherProps = omit(this.$props, [ 'prefixCls', 'autosize', 'type', ]) const attrs = { attrs: { ...otherProps, ...this.$attrs }, } return ( <textarea {...attrs} value={stateValue} class={getTextAreaClassName()} style={textareaStyles} onKeydown={handleKeyDown} onInput={handleTextareaChange} ref='textArea' /> ) }, } </script>