Browse Source

refactor: input

suzigang 4 years ago
parent
commit
4783f6eaa0

+ 2 - 2
src/packages/icon/doc.md

@@ -43,7 +43,7 @@ app.use(Icon);
 
 ```html
 <nut-icon name="dongdong"></nut-icon>
-<nut-icon name="dongdong" size="24px"></nut-icon>
+<nut-icon name="dongdong" size="24"></nut-icon>
 <nut-icon name="dongdong" size="16px"></nut-icon>
 ```
 
@@ -80,7 +80,7 @@ app.use(Icon);
 |--------------|----------------------------------|--------|------------------|
 | name         | 图标名称或图片链接               | String | -                |
 | color        | 图标颜色                         | String | -                |
-| size         | 图标大小,如 `20px` `2em` `2rem` | String | -                |
+| size         | 图标大小,如 `20px` `2em` `2rem` | String|Number | -                |
 | class-prefix | 类名前缀,用于使用自定义图标     | String | `nutui-iconfont` |
 | tag          | HTML 标签                        | String | `i`              |
 

+ 8 - 4
src/packages/icon/index.vue

@@ -6,7 +6,7 @@ const { componentName, create } = createComponent('icon');
 export default create({
   props: {
     name: { type: String, default: '' },
-    size: { type: String, default: '' },
+    size: { type: [String, Number], default: '' },
     classPrefix: { type: String, default: 'nutui-iconfont' },
     color: { type: String, default: '' },
     tag: { type: String as PropType<keyof HTMLElementTagNameMap>, default: 'i' }
@@ -22,6 +22,10 @@ export default create({
       return props.name ? props.name.indexOf('/') !== -1 : false;
     };
 
+    const pxCheck = (value: string | number) => {
+      return typeof value === 'number' ? `${value}px` : String(value);
+    };
+
     return () => {
       const _isImage = isImage();
       return h(
@@ -32,9 +36,9 @@ export default create({
             : `${props.classPrefix} ${componentName}-${props.name}`,
           style: {
             color: props.color,
-            fontSize: props.size,
-            width: _isImage ? props.size : '',
-            height: _isImage ? props.size : ''
+            fontSize: pxCheck(props.size),
+            width: _isImage ? pxCheck(props.size) : '',
+            height: _isImage ? pxCheck(props.size) : ''
           },
           onClick: handleClick,
           src: _isImage ? props.name : ''

+ 8 - 9
src/packages/input/demo.vue

@@ -6,14 +6,13 @@
       @change="change"
       @focus="focus"
       @blur="blur"
-      label="文本"
+      label="文本(异步)"
     />
-
     <nut-input
       placeholder="请输入文本"
       @change="change"
       v-model:value="state.val0"
-      :requireShow="true"
+      :require-show="true"
       label="文本"
       @clear="clear"
     />
@@ -34,28 +33,28 @@
     <nut-input
       v-model:value="state.val4"
       @change="change"
-      maxLength="7"
-      label="限制7"
+      max-length="7"
+      label="限制7"
     />
     <h2>自定义类型</h2>
     <nut-input
       v-model:value="state.val0"
       @change="change"
       type="password"
-      label="密码"
+      label="密码"
     />
     <nut-input
       v-model:value="state.val5"
       @change="change"
-      type="digit"
-      label="整数"
+      type="number"
+      label="整数"
     />
     <nut-input
       v-model:value="state.val6"
       @change="change"
       type="digit"
       placeholder="支持小数点的输入"
-      label="数字"
+      label="数字"
     />
   </div>
 </template>

+ 26 - 19
src/packages/input/doc.md

@@ -2,15 +2,16 @@
 
 ### 介绍
 
+单行输入框
 
 ### 安装
 
 ``` javascript
 import { createApp } from 'vue';
-import { input } from '@nutui/nutui';
+import { Input } from '@nutui/nutui';
 
 const app = createApp();
-app.use(input);
+app.use(Input);
 
 ```
 ## 代码演示
@@ -30,7 +31,7 @@ app.use(input);
 <nut-input placeholder="请输入文本"
       @change="change"
       v-model:value="state.val0"
-      :requireShow="true"
+      :require-show="true"
       label="文本"
       @clear="clear"
     />
@@ -47,34 +48,40 @@ app.use(input);
 ### 限制输入长度
 
 ```html
- <nut-input v-model:value="state.val4" @change="change" maxLength="7" label="限制7:" />
+ <nut-input v-model:value="state.val4" @change="change" max-length="7" label="限制7" />
 ```
 ### 其他类型
 
 ```html
-<nut-input v-model:value="state.val0" @change="change" type="password" label="密码"/>
-<nut-input v-model:value="state.val5" @change="change" type="digit" label="整数:" />
-<nut-input v-model:value="state.val6" @change="change" type="digit" placeholder="支持小数点的输入" label="数字"/>
+<nut-input v-model:value="state.val0" @change="change" type="password" label="密码"/>
+<nut-input v-model:value="state.val5" @change="change" type="number" label="整数" />
+<nut-input v-model:value="state.val6" @change="change" type="digit" placeholder="支持小数点的输入" label="数字"/>
 ```
 
 
+### Prop
 
 | 参数         | 说明                             | 类型   | 默认值           |
 |--------------|----------------------------------|--------|------------------|
-| type         | 类型,可选值为 `text` `textarea` `number`  等 | String |`text`         |
+| type         | 类型,可选值为 `text` `number`  等 | String |`text`         |
 | value      | 输入值,双向绑定 | String |  -     |
 | placeholder         | 为空时占位符 | String |       -       |
-| label          | 	左侧文案                       | string | -             |
-| requireShow          |左侧*号是否展示                       | boolean | `false`           |
-| disabled          | 	是否禁用                       | boolean | `false`              |
-| readonly          | 是否只读                        | boolean | `false`               |
-| maxlength          | 限制最长输入字符                   | string/number | -               |
-| disableClear          | 禁止展示清除icon                   | boolean | false             |
-| textAlign          | 文本位置                   | string | `left`             |
-| change          | 输入内容时触发                        | function | -               |
-| focus          | 聚焦时触发                        | function | -               |
-| blur          | 失焦时触发                        | function | -               |
-| clear          | 点击清空时触发                        | function | -               |
+| label          | 	左侧文案                       | String | -             |
+| require-show          |左侧*号是否展示                       | Boolean | `false`           |
+| disabled          | 	是否禁用                       | Boolean | `false`              |
+| readonly          | 是否只读                        | Boolean | `false`               |
+| max-length          | 限制最长输入字符                   | String、Number | -               |
+| disable-clear          | 禁止展示清除icon                   | Boolean | `false`             |
+| text-align          | 文本位置                   | String | `left`             |
+
+### Event
+
+| 名称  | 说明     | 回调参数    |
+|-------|----------|-------------|
+| change | 输入内容时触发 | val |
+| focus | 聚焦时触发 | val |
+| blur | 失焦时触发 | val |
+| clear | 点击清空时触发 | val |
 
 
 

+ 16 - 12
src/packages/input/index.scss

@@ -3,15 +3,16 @@
   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;
+    padding-right: 35px;
   }
-  .nut-input-label {
+  &-label {
     width: 80px;
     overflow: hidden;
     display: inline-block;
@@ -28,14 +29,17 @@
     position: absolute;
     right: 15px;
   }
-}
-.nut-input-disabled {
-  color: #c8c9cc !important;
-  input:disabled {
-    background: none;
-    color: #c8c9cc;
-    cursor: not-allowed;
-    opacity: 1;
-    -webkit-text-fill-color: #c8c9cc;
+  &-disabled {
+    color: $input-disabled-color !important;
+    input:disabled {
+      background: none;
+      color: $input-disabled-color;
+      cursor: not-allowed;
+      opacity: 1;
+      -webkit-text-fill-color: $input-disabled-color;
+    }
+  }
+  &-require {
+    color: $primary-color;
   }
 }

+ 47 - 48
src/packages/input/index.vue

@@ -12,7 +12,7 @@
       :placeholder="placeholder"
       :disabled="disabled"
       :readonly="readonly"
-      :value="state.curretvalue"
+      :value="curretvalue"
       @input="valueChange"
       @focus="valueFocus"
       @blur="valueBlur"
@@ -21,14 +21,14 @@
       @click="handleClear"
       class="nut-textinput-clear"
       v-if="!disableClear && !readonly"
-      v-show="active && state.curretvalue.length > 0"
+      v-show="active && curretvalue.length > 0"
     >
       <nut-icon name="close-little" size="12px"></nut-icon>
     </view>
   </view>
 </template>
 <script lang="ts">
-import { ref, toRefs, reactive, computed } from 'vue';
+import { toRefs, reactive, computed, watch } from 'vue';
 import { createComponent } from '@/utils/create';
 import { formatNumber } from './util';
 
@@ -72,7 +72,7 @@ export default create({
       default: 'left'
     },
     maxLength: {
-      type: String,
+      type: [String, Number],
       default: ''
     },
     disableClear: {
@@ -81,50 +81,46 @@ export default create({
     }
   },
 
-  emits: ['change', 'update:value', 'blur', 'focus', 'clear', 'error'],
+  emits: ['change', 'update:value', 'blur', 'focus', 'clear'],
 
   setup(props, { emit }) {
-    const {
-      label,
-      placeholder,
-      disabled,
-      readonly,
-      requireShow,
-      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,
+      active: false
     });
+
     const classes = computed(() => {
+      const prefixCls = componentName;
       return {
-        [componentName]: true,
-        'nut-input-disabled': disabled
+        [prefixCls]: true,
+        [`${prefixCls}-disabled`]: props.disabled
       };
     });
+
     const styles = computed(() => {
       return {
-        'text-align': props.textAlign
+        textAlign: props.textAlign
       };
     });
+
     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));
       }
-      if (props.type == 'digit') {
+      if (props.type === 'digit') {
         val = formatNumber(val, true);
       }
-      if (props.type == 'number') {
+      if (props.type === 'number') {
         val = formatNumber(val, false);
       }
       state.textNum = val.length;
@@ -139,11 +135,10 @@ export default create({
         }
       ]);
     };
+
     const valueFocus = (e: Event) => {
-      active.value = true;
+      state.active = true;
       const input = e.target as HTMLInputElement;
-      let val = input.value;
-      val = String(val);
       emitChange([
         {
           eventName: 'update:value',
@@ -151,58 +146,62 @@ export default create({
         },
         {
           eventName: 'focus',
-          params: [val]
+          params: [String(input.value)]
         }
       ]);
     };
+
     const valueBlur = (e: Event) => {
       setTimeout(() => {
-        active.value = false;
+        state.active = 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]
+          params: [String(input.value)]
         }
       ]);
     };
+
     const handleClear = () => {
-      const val = '';
       emitChange([
         {
           eventName: 'update:value',
-          params: [val]
+          params: ['']
         },
         {
           eventName: 'clear',
-          params: [val]
+          params: ['']
         }
       ]);
     };
+
+    watch(
+      () => props.value,
+      val => {
+        state.curretvalue = val;
+        emitChange([
+          {
+            eventName: 'update:value',
+            params: [String(val)]
+          }
+        ]);
+      }
+    );
+
     return {
-      value,
-      requireShow,
-      readonly,
-      placeholder,
-      label,
-      disabled,
-      state,
+      ...toRefs(state),
+      classes,
       styles,
-      active,
-      maxLength,
       valueChange,
       valueFocus,
       valueBlur,
-      handleClear,
-      classes,
-      emitChange
+      handleClear
     };
   }
 });

+ 1 - 1
src/packages/input/util.ts

@@ -20,7 +20,7 @@ export function formatNumber(
   if (allowDot) {
     value = trimExtraChar(value, '.', /\./g);
   } else {
-    value = value.split('.')[0];
+    value = value.replace(/\./g, '');
   }
 
   if (allowMinus) {

+ 4 - 0
src/styles/variables.scss

@@ -109,6 +109,10 @@ $uploader-width: 100px;
 $uploader-height: 100px;
 $uploader-background: #f7f8fa;
 
+//input
+$input-border-bottom: #eaf0fb;
+$input-disabled-color: #c8c9cc;
+
 // inputnumber
 
 $inputnumber-input-background-color: $help-color;