vxe-table-demonic
Version:
一个基于 vue 的 PC 端表单/表格组件,支持增删改查、虚拟列表、虚拟树、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、数据分页、弹窗、自定义模板、渲染器、JSON 配置式...
241 lines (240 loc) • 10.1 kB
JavaScript
import { defineComponent, h, ref, computed, nextTick, watch, reactive, inject } from 'vue';
import XEUtils from 'xe-utils';
import GlobalConfig from '../../v-x-e-table/src/conf';
import { getFuncText } from '../../tools/utils';
import { useSize } from '../../hooks/size';
var autoTxtElem;
export default defineComponent({
name: 'VxeTextarea',
props: {
modelValue: [String, Number],
className: String,
immediate: { type: Boolean, default: true },
name: String,
readonly: Boolean,
disabled: Boolean,
placeholder: {
type: 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: function () { return GlobalConfig.textarea.resize; } },
size: { type: String, default: function () { return GlobalConfig.textarea.size || GlobalConfig.size; } }
},
emits: [
'update:modelValue',
'input',
'keydown',
'keyup',
'click',
'change',
'focus',
'blur'
],
setup: function (props, context) {
var emit = context.emit;
var $xeform = inject('$xeform', null);
var $xeformiteminfo = inject('$xeformiteminfo', null);
var xID = XEUtils.uniqueId();
var computeSize = useSize(props);
var reactData = reactive({
inputValue: props.modelValue
});
var refElem = ref();
var refTextarea = ref();
var refMaps = {
refElem: refElem,
refTextarea: refTextarea
};
var $xetextarea = {
xID: xID,
props: props,
context: context,
reactData: reactData,
getRefMaps: function () { return refMaps; }
};
var textareaMethods = {};
var computeInputCount = computed(function () {
return XEUtils.getSize(reactData.inputValue);
});
var computeIsCountError = computed(function () {
var inputCount = computeInputCount.value;
return props.maxlength && inputCount > XEUtils.toNumber(props.maxlength);
});
var computeSizeOpts = computed(function () {
return Object.assign({ minRows: 1, maxRows: 10 }, GlobalConfig.textarea.autosize, props.autosize);
});
var updateAutoTxt = function () {
var size = props.size, autosize = props.autosize;
var inputValue = reactData.inputValue;
if (autosize) {
if (!autoTxtElem) {
autoTxtElem = document.createElement('div');
}
if (!autoTxtElem.parentNode) {
document.body.appendChild(autoTxtElem);
}
var textElem = refTextarea.value;
var textStyle = getComputedStyle(textElem);
autoTxtElem.className = ['vxe-textarea--autosize', size ? "size--".concat(size) : ''].join(' ');
autoTxtElem.style.width = "".concat(textElem.clientWidth, "px");
autoTxtElem.style.padding = textStyle.padding;
autoTxtElem.innerText = ('' + (inputValue || ' ')).replace(/\n$/, '\n ');
}
};
var handleResize = function () {
if (props.autosize) {
nextTick(function () {
var sizeOpts = computeSizeOpts.value;
var minRows = sizeOpts.minRows, maxRows = sizeOpts.maxRows;
var textElem = refTextarea.value;
var sizeHeight = autoTxtElem.clientHeight;
var textStyle = getComputedStyle(textElem);
var lineHeight = XEUtils.toNumber(textStyle.lineHeight);
var paddingTop = XEUtils.toNumber(textStyle.paddingTop);
var paddingBottom = XEUtils.toNumber(textStyle.paddingBottom);
var borderTopWidth = XEUtils.toNumber(textStyle.borderTopWidth);
var borderBottomWidth = XEUtils.toNumber(textStyle.borderBottomWidth);
var intervalHeight = paddingTop + paddingBottom + borderTopWidth + borderBottomWidth;
var rowNum = (sizeHeight - intervalHeight) / lineHeight;
var textRows = rowNum && /[0-9]/.test('' + rowNum) ? rowNum : Math.floor(rowNum) + 1;
var vaildRows = textRows;
if (textRows < minRows) {
vaildRows = minRows;
}
else if (textRows > maxRows) {
vaildRows = maxRows;
}
textElem.style.height = "".concat((vaildRows * lineHeight) + intervalHeight, "px");
});
}
};
var triggerEvent = function (evnt) {
var value = reactData.inputValue;
$xetextarea.dispatchEvent(evnt.type, { value: value }, evnt);
};
var emitUpdate = function (value, evnt) {
reactData.inputValue = value;
emit('update:modelValue', value);
if (XEUtils.toValueString(props.modelValue) !== value) {
textareaMethods.dispatchEvent('change', { value: value }, evnt);
// 自动更新校验状态
if ($xeform && $xeformiteminfo) {
$xeform.triggerItemEvent(evnt, $xeformiteminfo.itemConfig.field, value);
}
}
};
var inputEvent = function (evnt) {
var immediate = props.immediate;
var textElem = evnt.target;
var value = textElem.value;
reactData.inputValue = value;
if (immediate) {
emitUpdate(value, evnt);
}
$xetextarea.dispatchEvent('input', { value: value }, evnt);
handleResize();
};
var changeEvent = function (evnt) {
var immediate = props.immediate;
if (immediate) {
triggerEvent(evnt);
}
else {
emitUpdate(reactData.inputValue, evnt);
}
};
var blurEvent = function (evnt) {
var immediate = props.immediate;
var inputValue = reactData.inputValue;
if (!immediate) {
emitUpdate(inputValue, evnt);
}
$xetextarea.dispatchEvent('blur', { value: inputValue }, evnt);
};
textareaMethods = {
dispatchEvent: function (type, params, evnt) {
emit(type, Object.assign({ $textarea: $xetextarea, $event: evnt }, params));
},
focus: function () {
var textElem = refTextarea.value;
textElem.focus();
return nextTick();
},
blur: function () {
var textElem = refTextarea.value;
textElem.blur();
return nextTick();
}
};
Object.assign($xetextarea, textareaMethods);
watch(function () { return props.modelValue; }, function (val) {
reactData.inputValue = val;
updateAutoTxt();
});
nextTick(function () {
var autosize = props.autosize;
if (autosize) {
updateAutoTxt();
handleResize();
}
});
var renderVN = function () {
var _a;
var className = props.className, resize = props.resize, placeholder = props.placeholder, disabled = props.disabled, maxlength = props.maxlength, autosize = props.autosize, showWordCount = props.showWordCount, countMethod = props.countMethod, rows = props.rows, cols = props.cols;
var inputValue = reactData.inputValue;
var vSize = computeSize.value;
var isCountError = computeIsCountError.value;
var inputCount = computeInputCount.value;
return h('div', {
ref: refElem,
class: ['vxe-textarea', className, (_a = {},
_a["size--".concat(vSize)] = vSize,
_a['is--autosize'] = autosize,
_a['is--count'] = showWordCount,
_a['is--disabled'] = disabled,
_a['def--rows'] = !XEUtils.eqNull(rows),
_a['def--cols'] = !XEUtils.eqNull(cols),
_a)]
}, [
h('textarea', {
ref: refTextarea,
class: 'vxe-textarea--inner',
value: inputValue,
name: props.name,
placeholder: placeholder ? getFuncText(placeholder) : null,
maxlength: maxlength,
readonly: props.readonly,
disabled: disabled,
rows: rows,
cols: cols,
style: resize ? {
resize: resize
} : null,
onInput: inputEvent,
onChange: changeEvent,
onKeydown: triggerEvent,
onKeyup: triggerEvent,
onClick: triggerEvent,
onFocus: triggerEvent,
onBlur: blurEvent
}),
showWordCount ? h('span', {
class: ['vxe-textarea--count', {
'is--error': isCountError
}]
}, countMethod ? "".concat(countMethod({ value: inputValue })) : "".concat(inputCount).concat(maxlength ? "/".concat(maxlength) : '')) : null
]);
};
$xetextarea.renderVN = renderVN;
return $xetextarea;
},
render: function () {
return this.renderVN();
}
});