UNPKG

vxe-table-select-area

Version:

一个基于 vxe-table 的可区域选中复制、粘贴的组件

219 lines (216 loc) 6.53 kB
import XEUtils from 'xe-utils' import GlobalConfig from '../../v-x-e-table/src/conf' import vSize from '../../mixins/size' import { getFuncText } from '../../tools/utils' let autoTxtElem export default { name: 'VxeTextarea', mixins: [vSize], model: { prop: 'value', event: 'modelValue' }, props: { value: [String, Number], immediate: { type: Boolean, default: true }, name: String, readonly: Boolean, disabled: Boolean, placeholder: String, maxlength: [String, Number], rows: { type: [String, Number], default: 2 }, cols: { type: [String, Number], default: null }, showWordCount: Boolean, countMethod: Function, autosize: [Boolean, Object], form: String, resize: { type: String, default: () => GlobalConfig.textarea.resize }, className: String, size: { type: String, default: () => GlobalConfig.textarea.size || GlobalConfig.size } }, inject: { $xeform: { default: null }, $xeformiteminfo: { default: null } }, data () { return { inputValue: this.value } }, computed: { inputCount () { return XEUtils.getSize(this.inputValue) }, isCountError () { return this.maxlength && this.inputCount > XEUtils.toNumber(this.maxlength) }, defaultEvents () { const evnts = {} XEUtils.each(this.$listeners, (cb, name) => { if (['input', 'change', 'blur'].indexOf(name) === -1) { evnts[name] = this.triggerEvent } }) evnts.input = this.inputEvent evnts.change = this.changeEvent evnts.blur = this.blurEvent return evnts }, sizeOpts () { return Object.assign({ minRows: 1, maxRows: 10 }, GlobalConfig.textarea.autosize, this.autosize) } }, watch: { value (val) { this.inputValue = val this.updateAutoTxt() } }, mounted () { const { autosize } = this if (autosize) { this.updateAutoTxt() this.handleResize() } }, render (h) { const { className, defaultEvents, inputValue, vSize, name, form, resize, placeholder, readonly, disabled, maxlength, autosize, showWordCount, countMethod, rows, cols } = this const attrs = { name, form, placeholder, maxlength, readonly, disabled, rows, cols } if (placeholder) { attrs.placeholder = getFuncText(placeholder) } return h('div', { class: ['vxe-textarea', className, { [`size--${vSize}`]: vSize, 'is--autosize': autosize, 'is--disabled': disabled, 'def--rows': !XEUtils.eqNull(rows), 'def--cols': !XEUtils.eqNull(cols) }] }, [ h('textarea', { ref: 'textarea', class: 'vxe-textarea--inner', domProps: { value: inputValue }, attrs, style: resize ? { resize } : null, on: defaultEvents }), showWordCount ? h('span', { class: ['vxe-textarea--count', { 'is--error': this.isCountError }] }, countMethod ? `${countMethod({ value: inputValue })}` : `${this.inputCount}${maxlength ? `/${maxlength}` : ''}`) : null ]) }, methods: { focus () { this.$refs.textarea.focus() return this.$nextTick() }, blur () { this.$refs.textarea.blur() return this.$nextTick() }, triggerEvent (evnt) { const { inputValue } = this this.$emit(evnt.type, { value: inputValue, $event: evnt }) }, emitUpdate (value, evnt) { this.inputValue = value this.$emit('modelValue', value) if (this.value !== value) { this.$emit('change', { value, $event: evnt }) // 自动更新校验状态 if (this.$xeform && this.$xeformiteminfo) { this.$xeform.triggerItemEvent(evnt, this.$xeformiteminfo.itemConfig.field, value) } } }, inputEvent (evnt) { const { immediate } = this const value = evnt.target.value this.inputValue = value if (immediate) { this.emitUpdate(value, evnt) } this.handleResize() this.triggerEvent(evnt) }, changeEvent (evnt) { const { immediate } = this if (immediate) { this.triggerEvent(evnt) } else { this.emitUpdate(this.inputValue, evnt) } }, blurEvent (evnt) { const { inputValue, immediate } = this if (!immediate) { this.emitUpdate(inputValue, evnt) } this.$emit('blur', { value: inputValue, $event: evnt }) }, updateAutoTxt () { const { $refs, inputValue, size, autosize } = this if (autosize) { if (!autoTxtElem) { autoTxtElem = document.createElement('div') } if (!autoTxtElem.parentNode) { document.body.appendChild(autoTxtElem) } const textElem = $refs.textarea const textStyle = getComputedStyle(textElem) autoTxtElem.className = ['vxe-textarea--autosize', size ? `size--${size}` : ''].join(' ') autoTxtElem.style.width = `${textElem.clientWidth}px` autoTxtElem.style.padding = textStyle.padding autoTxtElem.innerHTML = ('' + (inputValue || ' ')).replace(/\n$/, '\n ') } }, handleResize () { if (this.autosize) { this.$nextTick(() => { const { $refs, sizeOpts } = this const { minRows, maxRows } = sizeOpts const textElem = $refs.textarea const sizeHeight = autoTxtElem.clientHeight const textStyle = getComputedStyle(textElem) const lineHeight = XEUtils.toNumber(textStyle.lineHeight) const paddingTop = XEUtils.toNumber(textStyle.paddingTop) const paddingBottom = XEUtils.toNumber(textStyle.paddingBottom) const borderTopWidth = XEUtils.toNumber(textStyle.borderTopWidth) const borderBottomWidth = XEUtils.toNumber(textStyle.borderBottomWidth) const intervalHeight = paddingTop + paddingBottom + borderTopWidth + borderBottomWidth const rowNum = (sizeHeight - intervalHeight) / lineHeight const textRows = rowNum && /[0-9]/.test(rowNum) ? rowNum : Math.floor(rowNum) + 1 let vaildRows = textRows if (textRows < minRows) { vaildRows = minRows } else if (textRows > maxRows) { vaildRows = maxRows } textElem.style.height = `${(vaildRows * lineHeight) + intervalHeight}px` }) } } } }