浏览代码

refactor: textarea

suzigang 4 年之前
父节点
当前提交
cb64e80383

+ 1 - 1
src/packages/input/doc.md

@@ -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
 

+ 6 - 17
src/packages/textarea/demo.vue

@@ -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
     };
   }
 });

+ 40 - 29
src/packages/textarea/doc.md

@@ -1,16 +1,17 @@
-# 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 |
 
 
 

+ 2 - 7
src/packages/textarea/index.scss

@@ -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;

+ 49 - 52
src/packages/textarea/index.vue

@@ -1,24 +1,26 @@
 <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
     };
   }
 });