OfficeSystem/node_modules/@climblee/uv-ui/components/uv-textarea/uv-textarea.vue
WindowBird 7ab9e16c35 init
2025-10-30 16:42:12 +08:00

238 lines
8.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="uv-textarea"
:class="textareaClass"
:style="[textareaStyle]">
<textarea class="uv-textarea__field"
:value="innerValue"
:style="[
{height: autoHeight ? 'auto' :$uv.addUnit(height)},
$uv.addStyle(textStyle)
]"
:placeholder="placeholder"
:placeholder-style="$uv.addStyle(placeholderStyle, 'string')"
:placeholder-class="placeholderClass"
:disabled="disabled"
:focus="focus"
:autoHeight="autoHeight"
:fixed="fixed"
:cursorSpacing="cursorSpacing"
:cursor="cursor"
:showConfirmBar="showConfirmBar"
:selectionStart="selectionStart"
:selectionEnd="selectionEnd"
:adjustPosition="adjustPosition"
:disableDefaultPadding="disableDefaultPadding"
:holdKeyboard="holdKeyboard"
:maxlength="maxlen"
:confirmType="confirmType"
:ignoreCompositionEvent="ignoreCompositionEvent"
:confirm-hold="confirmHold"
@focus="onFocus"
@blur="onBlur"
@linechange="onLinechange"
@input="onInput"
@confirm="onConfirm"
@keyboardheightchange="onKeyboardheightchange"></textarea>
<text class="uv-textarea__count"
:style="[{
'background-color': disabled ? 'transparent' : '#fff',
},$uv.addStyle(countStyle)]"
v-if="count && maxlen!=-1">{{ getCount }}/{{ maxlen }}</text>
</view>
</template>
<script>
import mpMixin from '../../libs/mixin/mpMixin.js'
import mixin from '../../libs/mixin/mixin.js'
import props from "./props.js";
/**
* Textarea 文本域
* @description 文本域此组件满足了可能出现的表单信息补充,编辑等实际逻辑的功能,内置了字数校验等
* @tutorial https://www.uvui.cn/components/textarea.html
*
* @property {String | Number} value / v-model 输入框的内容
* @property {String | Number} placeholder 输入框为空时占位符
* @property {String} placeholderClass 指定placeholder的样式类注意页面或组件的style中写了scoped时需要在类名前写/deep/ 默认 'input-placeholder'
* @property {String | Object} placeholderStyle 指定placeholder的样式字符串/对象形式,如"color: red;"
* @property {String | Number} height 输入框高度(默认 70
* @property {String} confirmType 设置键盘右下角按钮的文字仅微信小程序App-vue和H5有效默认 'done'
* @property {Boolean} disabled 是否禁用(默认 false
* @property {Boolean} count 是否显示统计字数(默认 false
* @property {Boolean} focus 是否自动获取焦点nvue不支持H5取决于浏览器的实现默认 false
* @property {Boolean | Function} autoHeight 是否自动增加高度(默认 false
* @property {Boolean} fixed 如果textarea是在一个position:fixed的区域需要显示指定属性fixed为true默认 false
* @property {Number} cursorSpacing 指定光标与键盘的距离(默认 0
* @property {String | Number} cursor 指定focus时的光标位置
* @property {Function} formatter 内容式化函数
* @property {Boolean} showConfirmBar 是否显示键盘上方带有”完成“按钮那一栏,(默认 true
* @property {Number} selectionStart 光标起始位置自动聚焦时有效需与selection-end搭配使用默认 -1
* @property {Number | Number} selectionEnd 光标结束位置自动聚焦时有效需与selection-start搭配使用默认 -1
* @property {Boolean} adjustPosition 键盘弹起时,是否自动上推页面(默认 true
* @property {Boolean | Number} disableDefaultPadding 是否去掉 iOS 下的默认内边距,只微信小程序有效(默认 false
* @property {Boolean} holdKeyboard focus时点击页面的时候不收起键盘只微信小程序有效默认 false
* @property {String | Number} maxlength 最大输入长度,设置为 -1 的时候不限制最大长度(默认 140
* @property {String} border 边框类型surround-四周边框none-无边框bottom-底部边框(默认 'surround'
* @property {Boolean} ignoreCompositionEvent 是否忽略组件内对文本合成系统事件的处理
* @property {Boolean} confirmHold 点击键盘右下角按钮时是否保持键盘不收起
* @property {Object} textStyle 文本样式
* @property {Object} countStyle 统计数字的样式
*
* @event {Function(e)} focus 输入框聚焦时触发event.detail = { value, height }height 为键盘高度
* @event {Function(e)} blur 输入框失去焦点时触发event.detail = {value, cursor}
* @event {Function(e)} linechange 输入框行数变化时调用event.detail = {height: 0, heightRpx: 0, lineCount: 0}
* @event {Function(e)} input 当键盘输入时,触发 input 事件
* @event {Function(e)} confirm 点击完成时, 触发 confirm 事件
* @event {Function(e)} keyboardheightchange 键盘高度发生变化的时候触发此事件
* @example <uv--textarea v-model="value1" placeholder="请输入内容" ></uv--textarea>
*/
export default {
name: "uv-textarea",
mixins: [mpMixin, mixin, props],
data() {
return {
// 输入框的值
innerValue: "",
// 是否处于获得焦点状态
focused: false,
// 过滤处理方法
innerFormatter: value => value
}
},
created() {
// #ifndef VUE3
this.innerValue = this.value;
// #endif
// #ifdef VUE3
this.innerValue = this.modelValue;
// #endif
},
watch: {
value(newVal) {
this.innerValue = newVal;
},
modelValue(newVal) {
this.innerValue = newVal;
}
},
computed: {
// 组件的类名
textareaClass() {
let classes = [],
{ border, disabled } = this;
border === "surround" && (classes = classes.concat(["uv-border", "uv-textarea--radius"]));
border === "bottom" && (classes = classes.concat(["uv-border-bottom", "uv-textarea--no-radius", ]));
disabled && classes.push("uv-textarea--disabled");
return classes.join(" ");
},
// 组件的样式
textareaStyle() {
const style = {};
// #ifdef APP-NVUE
// 由于textarea在安卓nvue上的差异性需要额外再调整其内边距
if (this.$uv.os() === "android") {
style.paddingTop = "6px";
style.paddingLeft = "9px";
style.paddingBottom = "3px";
style.paddingRight = "6px";
}
// #endif
return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle));
},
maxlen() {
return this.maxlength < 0 ? this.maxlength < 0 ? -1 : 140 : this.maxlength;
},
getCount() {
try{
return this.innerValue.length > this.maxlen ? this.maxlen: this.innerValue.length;
}catch(e){
return 0;
}
}
},
methods: {
// 在微信小程序中不支持将函数当做props参数故只能通过ref形式调用
setFormatter(e) {
this.innerFormatter = e
},
onFocus(e) {
this.$emit("focus", e);
},
onBlur(e) {
this.$emit("blur", e);
// 尝试调用uv-form的验证方法
this.$uv.formValidate(this, "blur");
},
onLinechange(e) {
this.$emit("linechange", e);
},
onInput(e) {
let { value = "" } = e.detail || {};
// 格式化过滤方法
const formatter = this.formatter || this.innerFormatter
const formatValue = formatter(value)
// 为了避免props的单向数据流特性需要先将innerValue值设置为当前值再在$nextTick中重新赋予设置后的值才有效
this.innerValue = value
this.$nextTick(() => {
this.innerValue = formatValue;
this.valueChange();
})
},
// 内容发生变化,进行处理
valueChange() {
const value = this.innerValue;
this.$nextTick(() => {
this.$emit("input", value);
this.$emit("update:modelValue", value);
this.$emit("change", value);
// 尝试调用uv-form的验证方法
this.$uv.formValidate(this, "change");
});
},
onConfirm(e) {
this.$emit("confirm", e);
},
onKeyboardheightchange(e) {
this.$emit("keyboardheightchange", e);
},
},
};
</script>
<style lang="scss" scoped>
$show-border: 1;
$show-border-surround: 1;
$show-border-bottom: 1;
@import '../../libs/css/variable.scss';
@import '../../libs/css/components.scss';
@import '../../libs/css/color.scss';
.uv-textarea {
border-radius: 4px;
background-color: #fff;
position: relative;
@include flex;
flex: 1;
padding: 9px;
&--radius {
border-radius: 4px;
}
&--no-radius {
border-radius: 0;
}
&--disabled {
background-color: #f5f7fa;
}
&__field {
flex: 1;
font-size: 15px;
color: $uv-content-color;
width: 100%;
}
&__count {
position: absolute;
right: 5px;
bottom: 2px;
font-size: 12px;
color: $uv-tips-color;
background-color: #ffffff;
padding: 1px 4px;
}
}
</style>