浏览代码

Merge branch 'next' of https://github.com/jdf2e/nutui into next

richard1015 4 年之前
父节点
当前提交
b49fd38199
共有 3 个文件被更改,包括 114 次插入63 次删除
  1. 18 7
      src/packages/inputnumber/demo.vue
  2. 23 12
      src/packages/inputnumber/doc.md
  3. 73 44
      src/packages/inputnumber/index.vue

+ 18 - 7
src/packages/inputnumber/demo.vue

@@ -38,12 +38,12 @@
         @blur="blur"
       />
     </nut-cell>
-    <h2>支持异步修改(点击+/-,手动改成了3)</h2>
+    <h2>支持异步修改</h2>
     <nut-cell>
       <nut-inputnumber
         :async="state.async"
-        @change="handleChangeAsync"
-        v-model:modelValue="state.val5"
+        v-model="state.val5"
+        :before-change="beforeChange"
       />
     </nut-cell>
   </div>
@@ -65,7 +65,8 @@ export default createDemo({
       step: 1.1,
       min: 3,
       max: 100,
-      async: true
+      async: true,
+      timer: undefined as undefined | number
     });
     onMounted(() => {
       state.max = 5;
@@ -85,9 +86,18 @@ export default createDemo({
     const reduceNoAllow = () => {
       alert('超出最小限制数');
     };
+    const beforeChange = () => {
+      // return true;
+      return new Promise(resolve => {
+        setTimeout(() => {
+          resolve(true);
+        }, 500);
+      });
+    };
     const handleChangeAsync = (num: number) => {
-      setTimeout(() => {
-        state.val5 = 3;
+      clearTimeout(state.timer);
+      state.timer = setTimeout(() => {
+        state.val5 = state.val5 + 1;
       }, 1000);
     };
     return {
@@ -97,7 +107,8 @@ export default createDemo({
       focus,
       reduceNoAllow,
       addNoAllow,
-      handleChangeAsync
+      handleChangeAsync,
+      beforeChange
     };
   }
 });

+ 23 - 12
src/packages/inputnumber/doc.md

@@ -2,7 +2,7 @@
 
 ### 介绍
 
-基于
+由加、减按钮以及输入框组成,用于输入一定范围的数字。
 
 ### 安装
 
@@ -59,10 +59,21 @@ app.use(inputnumber);
 
 ### 高级用法
 
-`async`支持异步修改数量,设置了此属性为true,必须同时在`change`事件中手动设置input值才能生效
+`before-change`支持异步修改数量
 
 ```html
-<nut-inputnumber v-model:modelValue="1" :async="true" @change="change"/>
+<nut-inputnumber v-model:modelValue="1" :before-change="true"/>
+```
+
+```js
+  const beforeChange = () => {
+    // return true;
+    return new Promise(resolve => {
+      setTimeout(() => {
+        resolve(true);
+      }, 500);
+    });
+  };
 ```
 
 
@@ -72,16 +83,16 @@ app.use(inputnumber);
 
 | 参数         | 说明                             | 类型   | 默认值           |
 |--------------|----------------------------------|--------|------------------|
-| size         | 操作符+、-尺寸               | String          | 20px                |
-| color        | 操作符+、-颜色               | String          | #1a1a1a             |
-| dis-color     | 操作符+、-禁用时颜色          | String          | #ccc                |
-| min          | 最小值                      | String、Number | 1                   |
-| max          | 最大值                      | String、Number | Infinity             |
-| step         | 步长                        | String、Number |     1                |
+| size         | 操作符+、-尺寸               | String          | `20px`                |
+| color        | 操作符+、-颜色               | String          | `#1a1a1a `            |
+| dis-color     | 操作符+、-禁用时颜色          | String          | `#ccc`                |
+| min          | 最小值                      | String、Number | `1`                   |
+| max          | 最大值                      | String、Number | `Infinity`             |
+| step         | 步长                        | String、Number |     `1`                |
 | readonly     | 只读                   | Boolean | false              |
-| modelValue   | 初始值                   | String、Number | ''              |
-| decimal-places| 设置保留的小数位                   | String、Number | 1              |
-| async        | 支持异步                   | Boolean | false              |
+| modelValue   | 初始值                   | String、Number | `''`              |
+| decimal-places| 设置保留的小数位                   | String、Number | `1`              |
+| before-change        | 支持异步                   | Function | -              |
 
 ### Events
 

+ 73 - 44
src/packages/inputnumber/index.vue

@@ -76,9 +76,8 @@ export default create({
       type: [String, Number],
       default: 0
     },
-    async: {
-      type: Boolean,
-      default: false
+    beforeChange: {
+      type: Function
     }
   },
   emits: [
@@ -100,6 +99,47 @@ export default create({
       tempVal: '',
       focusing: false
     });
+
+    const classes = computed(() => {
+      const prefixCls = componentName;
+      return {
+        [prefixCls]: true
+      };
+    });
+
+    const isPromise = (obj: any) => {
+      return (
+        !!obj &&
+        (typeof obj === 'object' || typeof obj === 'function') &&
+        typeof obj.then === 'function'
+      );
+    };
+
+    const callInterceptor = (
+      interceptor: Function,
+      done: Function,
+      fail?: Function
+    ) => {
+      const res = interceptor.apply(null, arguments || []);
+      if (interceptor) {
+        if (isPromise(res)) {
+          res.then((value: boolean) => {
+            if (value) {
+              done();
+            } else {
+              fail && fail();
+            }
+          });
+        } else if (res) {
+          done();
+        } else if (fail) {
+          fail();
+        }
+      } else {
+        done();
+      }
+    };
+
     const format = (v: string | number): string | number => {
       if (v > max.value) {
         v = max.value;
@@ -137,19 +177,19 @@ export default create({
       });
     };
 
-    const classes = computed(() => {
-      const prefixCls = componentName;
-      return {
-        [prefixCls]: true
-      };
-    });
-
     const numChange = (e: Event) => {
       const input = e.target as HTMLInputElement;
       let val = input.value;
       val = String(format(val));
       input.value = val;
-      state.num = val;
+      if (props.beforeChange) {
+        callInterceptor(props.beforeChange, () => {
+          state.num = val;
+        });
+      } else {
+        state.num = val;
+      }
+
       emitChange([
         {
           eventName: 'update:modelValue',
@@ -177,18 +217,15 @@ export default create({
     };
 
     const blur = (e: Event) => {
-      if (props.async) {
-        emitChange([
-          {
-            eventName: 'change',
-            params: ['']
-          }
-        ]);
-        return;
-      }
       const val = (e.target as HTMLInputElement).value;
       state.minVal = String(min.value);
-      state.num = val ? format(val) : state.tempVal;
+      if (props.beforeChange) {
+        callInterceptor(props.beforeChange, () => {
+          state.num = val ? format(val) : state.tempVal;
+        });
+      } else {
+        state.num = val ? format(val) : state.tempVal;
+      }
       state.focusing = false;
       emitChange([
         {
@@ -203,21 +240,19 @@ export default create({
     };
 
     const reduce = () => {
-      if (props.async) {
-        emitChange([
-          {
-            eventName: 'change',
-            params: [state.num]
-          }
-        ]);
-        return;
-      }
       if (getIconColor('minus') === props.color) {
         const [n1, n2] = fixedDecimalPlaces(
           Number(state.num) - Number(props.step)
         ).split('.');
         const fixedLen = n2 ? n2.length : 0;
-        state.num = parseFloat(n1 + (n2 ? `.${n2}` : '')).toFixed(fixedLen);
+        if (props.beforeChange) {
+          callInterceptor(props.beforeChange, () => {
+            state.num = parseFloat(n1 + (n2 ? `.${n2}` : '')).toFixed(fixedLen);
+          });
+        } else {
+          state.num = parseFloat(n1 + (n2 ? `.${n2}` : '')).toFixed(fixedLen);
+        }
+
         emitChange([
           {
             eventName: 'update:modelValue',
@@ -239,21 +274,18 @@ export default create({
     };
 
     const add = () => {
-      if (props.async) {
-        emitChange([
-          {
-            eventName: 'change',
-            params: [state.num]
-          }
-        ]);
-        return;
-      }
       if (getIconColor('plus') === props.color) {
         const [n1, n2] = fixedDecimalPlaces(
           Number(state.num) + Number(props.step)
         ).split('.');
         const fixedLen = n2 ? n2.length : 0;
-        state.num = parseFloat(n1 + (n2 ? '.' + n2 : '')).toFixed(fixedLen);
+        if (props.beforeChange) {
+          callInterceptor(props.beforeChange, () => {
+            state.num = parseFloat(n1 + (n2 ? '.' + n2 : '')).toFixed(fixedLen);
+          });
+        } else {
+          state.num = parseFloat(n1 + (n2 ? '.' + n2 : '')).toFixed(fixedLen);
+        }
         emitChange([
           {
             eventName: 'update:modelValue',
@@ -302,10 +334,7 @@ export default create({
     return {
       state,
       classes,
-      format,
       getIconColor,
-      fixedDecimalPlaces,
-      emitChange,
       numChange,
       blur,
       focus,