提交 cb64e803 编写于 作者: S suzigang

refactor: textarea

上级 4783f6ea
......@@ -72,7 +72,7 @@ app.use(Input);
| readonly | 是否只读 | Boolean | `false` |
| max-length | 限制最长输入字符 | String、Number | - |
| disable-clear | 禁止展示清除icon | Boolean | `false` |
| text-align | 文本位置 | String | `left` |
| text-align | 文本位置,可选值`left`,`center`,`right` | String | `left` |
### Event
......
......@@ -4,7 +4,7 @@
<nut-textarea
v-model:value="state.val0"
@change="change"
rows="5"
rows="10"
placeholder="高度可拉伸"
:autosize="true"
label="留言:"
......@@ -14,12 +14,13 @@
v-model:value="state.val1"
@change="change"
rows="5"
:limitShow="true"
maxLength="20"
type="textarea"
:limit-show="true"
max-length="20"
placeholder="设置输入五行"
label="留言:"
/>
<h2>只读</h2>
<nut-textarea readonly="true" rows="5" placeholder="只读" label="留言:" />
</div>
</template>
......@@ -39,22 +40,10 @@ export default createDemo({
const change = (num: string | number) => {
console.log('change: ', num);
};
const focus = (num: string | number) => {
console.log('focus:', num);
};
const blur = (num: string | number) => {
console.log('blur:', num);
};
const clear = (num: string | number) => {
console.log('clear:', num);
};
return {
state,
change,
blur,
clear,
focus
change
};
}
});
......
# Input 输入框组件
# Textarea 文本域组件
### 介绍
支持多行文本
### 安装
``` javascript
import { createApp } from 'vue';
import { input } from '@nutui/nutui';
import { Textarea } from '@nutui/nutui';
const app = createApp();
app.use(input);
app.use(Textarea);
```
## 代码演示
......@@ -20,13 +21,13 @@ app.use(input);
```html
<nut-textarea
v-model:value="state.val0"
@change="change"
rows="5"
placeholder="高度可拉伸"
:autosize="true"
label="留言:"
/>
v-model:value="state.val0"
@change="change"
rows="5"
placeholder="高度可拉伸"
:autosize="true"
label="留言:"
/>
```
### 显示字数统计
......@@ -34,31 +35,41 @@ app.use(input);
```html
<nut-textarea
v-model:value="state.val1"
@change="change"
rows="5"
:limitShow="true"
maxLength="20"
type="textarea"
placeholder="设置输入五行"
label="留言:"
/>
v-model:value="state.val1"
@change="change"
rows="5"
:limit-show="true"
max-length="20"
type="textarea"
placeholder="设置输入五行"
label="留言:"
/>
```
### Prop
| 参数 | 说明 | 类型 | 默认值 |
|--------------|----------------------------------|--------|------------------|
| value | 输入值,双向绑定 | String | - |
| placeholder | 为空时占位符 | String | - |
| label | 左侧文案 | string | - |
| maxlength | 限制最长输入字符 | string/number | - |
| rows | textarea时高度 | string/number | 2 |
| limit-show | textarea时是否展示输入字符。须设置maxlength | boolean | `false` |
| change | 输入内容时触发 | function | - |
| focus | 聚焦时触发 | function | - |
| blur | 失焦时触发 | function | - |
| clear | 点击清空时触发 | function | - |
| value | 输入值,支持双向绑定 | String | - |
| placeholder | 为空时占位符 | String | `'请输入信息'` |
| label | 左侧文案 | String | - |
| max-length | 限制最长输入字符 | String、Number | - |
| rows | textarea的高度 | String、Number | `2` |
| limit-show | textarea是否展示输入字符。须配合`max-length`使用 | Boolean | `false` |
| autosize | 高度是否可拉伸 | Boolean | `false` |
| text-align | 文本位置,可选值`left`,`center`,`right` | String | `left` |
| readonly | 只读属性 | Boolean | `false` |
| disabled | 禁用属性 | Boolean | `false` |
### Event
| 名称 | 说明 | 回调参数 |
|-------|----------|-------------|
| change | 输入内容时触发 | val |
| focus | 聚焦时触发 | val |
| blur | 失焦时触发 | val |
......
......@@ -3,14 +3,9 @@
width: 100%;
padding: 10px 0px 10px 25px;
display: flex;
background: rgba(255, 255, 255, 1);
border-bottom: 1px solid rgba(234, 240, 251, 1);
background: $white;
border-bottom: 1px solid $input-border-bottom;
font-size: 14px;
input {
width: 230px;
flex: 1;
padding: 0 10px;
}
.nut-input-label {
width: 80px;
overflow: hidden;
......
<template>
<view class="nut-textarea">
<view :class="classes">
<view class="nut-input-label">
<view v-if="props.label" class="label-string">{{ props.label }}</view>
<view v-if="label" class="label-string">{{ label }}</view>
</view>
<view class="nut-text">
<textarea
:style="styles"
:rows="props.rows"
:rows="rows"
@input="valueChange"
v-model="state.curretvalue"
@focus="valueFocus"
@blur="valueBlur"
v-model="curretvalue"
class="nut-text-core"
:maxlength="maxLength"
:placeholder="props.placeholder"
:disabled="props.disabled"
:readonly="props.readonly"
:placeholder="placeholder"
:disabled="disabled"
:readonly="readonly"
>
</textarea>
<view class="nut-text-limit" v-if="limitShow">
<view :class="[{ 'nut-field-over': state.textNum > maxLength }]">{{
state.textNum
<view :class="[{ 'nut-field-over': textNum > maxLength }]">{{
textNum
}}</view>
<view>/{{ maxLength }}</view>
</view>
......@@ -26,12 +28,12 @@
</view>
</template>
<script lang="ts">
import { ref, toRefs, reactive, computed } from 'vue';
import { toRefs, reactive, computed, watch } from 'vue';
import { createComponent } from '@/utils/create';
const { componentName, create } = createComponent('textarea');
interface Events {
eventName: 'change' | 'focus' | 'blur' | 'clear' | 'update:value';
eventName: 'change' | 'focus' | 'blur' | 'update:value';
params: (string | number | Event)[];
}
export default create({
......@@ -49,8 +51,8 @@ export default create({
default: ''
},
rows: {
type: String,
default: ''
type: [String, Number],
default: '2'
},
label: {
type: String,
......@@ -78,38 +80,40 @@ export default create({
}
},
emits: ['change', 'update:value', 'blur', 'focus', 'clear', 'error'],
emits: ['change', 'update:value', 'blur', 'focus'],
setup(props, { emit }) {
const { maxLength } = props;
const { value } = toRefs(props);
const active = ref(false);
const state = reactive({
curretvalue: value,
textNum: String(value.value).length
curretvalue: props.value,
textNum: String(props.value).length
});
const classes = computed(() => {
const prefixCls = componentName;
return {
[componentName]: true
[prefixCls]: true
};
});
const styles = computed(() => {
return {
'text-align': props.textAlign,
textAlign: props.textAlign,
resize: props.autosize ? 'vertical' : 'none'
};
});
const emitChange = (envs: Array<Events>) => {
envs.forEach((item: Events) => {
return emit(item.eventName, ...item.params);
});
};
const valueChange = (e: Event) => {
const input = e.target as HTMLInputElement;
let val = input.value;
if (maxLength && val.length > Number(maxLength)) {
val = val.slice(0, Number(maxLength));
if (props.maxLength && val.length > Number(props.maxLength)) {
val = val.slice(0, Number(props.maxLength));
}
state.textNum = val.length;
emitChange([
......@@ -123,8 +127,8 @@ export default create({
}
]);
};
const valueFocus = (e: Event) => {
active.value = true;
const input = e.target as HTMLInputElement;
let val = input.value;
val = String(val);
......@@ -139,49 +143,42 @@ export default create({
}
]);
};
const valueBlur = (e: Event) => {
setTimeout(() => {
active.value = false;
}, 400);
const input = e.target as HTMLInputElement;
let val = input.value;
val = String(val);
emitChange([
{
eventName: 'update:value',
params: [val]
params: [String(input.value)]
},
{
eventName: 'blur',
params: [val]
}
]);
};
const handleClear = () => {
const val = '';
emitChange([
{
eventName: 'update:value',
params: [val]
},
{
eventName: 'clear',
params: [val]
params: [String(input.value)]
}
]);
};
watch(
() => props.value,
val => {
state.curretvalue = val;
state.textNum = String(val).length;
emitChange([
{
eventName: 'update:value',
params: [String(val)]
}
]);
}
);
return {
props,
value,
state,
...toRefs(state),
classes,
styles,
active,
maxLength,
valueChange,
valueFocus,
valueBlur,
handleClear,
emitChange
valueBlur
};
}
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册