Browse Source

feat: taro toast

richard1015 4 years ago
parent
commit
0f01e32ca7

+ 1 - 0
src/config.json

@@ -167,6 +167,7 @@
         },
         {
           "name": "Toast",
+          "taro": true,
           "sort": "1",
           "cName": "吐司",
           "type": "methods",

+ 4 - 1
src/packages/__VUE/notify/index.taro.vue

@@ -79,7 +79,10 @@ export default create({
     };
 
     const onAfterLeave = () => {
-      clearTimer();
+      if (props.visible) {
+        clearTimer();
+        hide();
+      }
     };
     return { hide, onAfterLeave, onClick };
   }

+ 90 - 0
src/packages/__VUE/toast/doc.taro.md

@@ -0,0 +1,90 @@
+# Toast 吐司
+
+轻提示。
+
+### 介绍
+
+用于轻提示。
+
+### 安装
+
+``` javascript
+import { createApp } from 'vue';
+import { Toast } from '@nutui/nutui@taro';
+
+const app = createApp();
+app.use(Toast);
+```
+
+## 代码示例
+
+``` html
+<nut-toast :msg="page.state.msg" v-model:visible="page.state.show" :type="page.state.type" @closed="page.methods.onClosed" :cover="page.state.cover" />
+<nut-cell title="Text 文字提示" is-link @click="page.methods.openToast('text','网络失败,请稍后再试~')"></nut-cell>
+<nut-cell title="Success 成功提示" is-link @click="page.methods.openToast('success','成功提示')"></nut-cell>
+<nut-cell title="Error 失败提示" is-link @click="page.methods.openToast('fail','失败提示')"></nut-cell>
+<nut-cell title="Warning 警告提示" is-link @click="page.methods.openToast('warn','警告提示')"></nut-cell>
+<nut-cell title="Loading 加载提示" is-link @click="page.methods.openToast('loading','加载中')"></nut-cell>
+<nut-cell title="Loading 带白色背景遮罩" is-link @click="page.methods.openToast('loading','加载中',true)"></nut-cell>
+```
+``` javascript
+import { reactive } from 'vue';
+export default {
+  setup() {
+    const page = {
+      state: reactive({
+        msg: 'toast',
+        type: 'text',
+        show: false,
+        cover: false
+      }),
+      methods: {
+        openToast: (type: string, msg: string, cover: boolean = false) => {
+          page.state.show = true;
+          page.state.msg = msg;
+          page.state.type = type;
+          page.state.cover = cover;
+        },
+        onClosed: () => console.log('closed')
+      }
+    };
+    return {
+      page
+    };
+  }
+};
+```
+### 基本用法
+
+
+### API
+| 方法名        | 说明         | 参数            | 返回值     |
+|---------------|--------------|-----------------|------------|
+| Toast.text    | 展示文字提示 | options/message | toast 实例 |
+| Toast.success | 展示成功提示 | options/message | toast 实例 |
+| Toast.fail    | 展示失败提示 | options/message | toast 实例 |
+| Toast.warn    | 展示警告提示 | options/message | toast 实例 |
+| Toast.hide    | 关闭提示     | force:boolean   | void       |
+| Toast.loading | 展示加载提示 | options/message | toast 实例 |
+
+## Props
+
+| 字段                   | 说明                                                                          | 类型          | 默认值                        |
+|------------------------|-------------------------------------------------------------------------------|---------------|-------------------------------|
+| msg                    | 消息文本内容,支持传入HTML                                                     | String/VNode  | ""                            |
+| duration               | 展示时长(毫秒)<br>值为 0 时,toast 不会自动消失(loading类型默认为0)       | Number        | 2000                          |
+| center                 | 是否展示在页面中部(为false时展示在底部)                                     | Boolean       | true                          |
+| bottom                 | 距页面底部的距离(像素),center为false时生效                                 | Number        | 30                            |
+| text-align-center      | 多行文案是否居中                                                              | Boolean       | true                          |
+| bg-color               | 背景颜色(透明度)                                                            | String        | "rgba(0, 0, 0, 0.8)"          |
+| custom-class           | 自定义类名                                                                    | String        | ""                            |
+| icon                   | 自定义图标,**对应icon组件,支持图片链接**                                    | String        | ""                            |
+| size                   | 文案尺寸,**small**/**base**/**large**三选一                                  | String        | "base"                        |
+| cover                  | 是否显示遮罩层,loading类型默认显示                                           | Boolean       | loading类型true/其他类型false |
+| cover-color            | 遮罩层颜色,默认透明                                                          | String        | "rgba(0,0,0,0)"               |
+| loading-rotate         | loading图标是否旋转,仅对loading类型生效                                      | Boolean       | true                          |
+| on-close               | 关闭时触发的事件                                                              | function      | null                          |
+| close-on-click-overlay | 是否在点击遮罩层后关闭提示                                                    | Boolean       | false                         |
+| toast-style            | 提示框style                                                                   | object        | {}                            |
+| toast-class            | 提示框class                                                                   | String        | ""                            |
+

+ 184 - 0
src/packages/__VUE/toast/index.taro.vue

@@ -0,0 +1,184 @@
+<template>
+  <Transition name="toast-fade" @after-leave="onAfterLeave">
+    <view
+      :class="toastBodyClass"
+      v-show="visible"
+      :style="{
+        bottom: center ? 'auto' : bottom + 'px',
+        'background-color': coverColor
+      }"
+      @click="clickCover"
+    >
+      <template v-if="$slots.default">
+        <slot></slot>
+      </template>
+      <template v-else>
+        <view
+          class="nut-toast-inner"
+          :style="{
+            'text-align': textAlignCenter ? 'center' : 'left',
+            'background-color': bgColor
+          }"
+        >
+          <view v-if="hasIcon" class="nut-toast-icon-wrapper">
+            <nut-icon size="20" color="#ffffff" :name="iconName"></nut-icon>
+          </view>
+          <view class="nut-toast-text" v-html="msg"></view>
+        </view>
+      </template>
+    </view>
+  </Transition>
+</template>
+<script>
+import { computed, watch } from 'vue';
+import { createComponent } from '../../utils/create';
+const { create } = createComponent('toast');
+import Icon from '../icon/index.vue';
+export default create({
+  components: {
+    [Icon.name]: Icon
+  },
+  props: {
+    id: String,
+    msg: String,
+    duration: {
+      type: Number,
+      default: 2000
+    },
+    center: {
+      type: Boolean,
+      default: true
+    },
+    type: {
+      type: String,
+      default: 'text'
+    },
+    customClass: String,
+    bottom: {
+      type: Number,
+      default: 30
+    },
+    size: {
+      type: [String, Number],
+      default: 'base'
+    },
+    icon: String,
+    textAlignCenter: {
+      type: Boolean,
+      default: true
+    },
+    loadingRotate: {
+      type: Boolean,
+      default: true
+    },
+    bgColor: {
+      type: String,
+      default: 'rgba(0, 0, 0, .8)'
+    },
+
+    onClose: Function,
+    unmount: Function,
+    cover: {
+      type: Boolean,
+      default: false
+    },
+    coverColor: {
+      type: String,
+      default: 'rgba(0, 0, 0, 0)'
+    },
+    closeOnClickOverlay: {
+      type: Boolean,
+      default: false
+    },
+    visible: {
+      type: Boolean,
+      default: false
+    }
+  },
+  emits: ['update:visible', 'closed'],
+  setup(props, { emit }) {
+    let timer;
+    const clearTimer = () => {
+      if (timer) {
+        clearTimeout(timer);
+        timer = null;
+      }
+    };
+    const hide = () => {
+      emit('update:visible', false);
+      emit('closed');
+    };
+    const show = () => {
+      clearTimer();
+      if (props.duration) {
+        timer = setTimeout(() => {
+          hide();
+        }, props.duration);
+      }
+    };
+    const clickCover = () => {
+      if (props.closeOnClickOverlay) {
+        hide();
+      }
+    };
+
+    watch(
+      () => props.visible,
+      (val) => {
+        if (val) {
+          show();
+        }
+      }
+    );
+
+    const hasIcon = computed(() => {
+      if (props.type !== 'text') {
+        return true;
+      } else {
+        return !!props.icon;
+      }
+    });
+    const iconName = computed(() => {
+      if (props.icon) {
+        return props.icon;
+      } else {
+        return {
+          success: 'success',
+          fail: 'failure',
+          warn: 'tips',
+          loading: 'loading'
+        }[props.type];
+      }
+    });
+    const toastBodyClass = computed(() => {
+      return [
+        'nut-toast',
+        { 'nut-toast-center': props.center },
+        { 'nut-toast-has-icon': hasIcon.value },
+        { 'nut-toast-cover': props.cover },
+        { 'nut-toast-loading': props.type === 'loading' },
+        props.customClass,
+        'nut-toast-' + props.size
+      ];
+    });
+
+    const onAfterLeave = () => {
+      if (props.visible) {
+        clearTimer();
+        hide();
+      }
+    };
+
+    return {
+      clickCover,
+      hasIcon,
+      iconName,
+      toastBodyClass,
+      onAfterLeave
+    };
+  }
+});
+</script>
+<style lang="scss">
+@import 'index.scss';
+</style>

+ 2 - 1
src/sites/mobile-taro/vue/src/app.config.ts

@@ -1,5 +1,6 @@
 export default {
   pages: [
+    'pages/toast/index',
     'pages/notify/index',
     'pages/dialog/index',
     'pages/range/index',
@@ -35,7 +36,7 @@ export default {
   window: {
     backgroundTextStyle: 'light',
     navigationBarBackgroundColor: '#fff',
-    navigationBarTitleText: 'WeChat',
+    navigationBarTitleText: 'NutUI',
     navigationBarTextStyle: 'black'
   }
 };

+ 3 - 0
src/sites/mobile-taro/vue/src/pages/toast/index.config.ts

@@ -0,0 +1,3 @@
+export default {
+  navigationBarTitleText: 'Toast'
+};

+ 72 - 0
src/sites/mobile-taro/vue/src/pages/toast/index.vue

@@ -0,0 +1,72 @@
+<template>
+  <div class="demo">
+    <h2>基本用法</h2>
+    <nut-toast
+      :msg="page.state.msg"
+      v-model:visible="page.state.show"
+      :type="page.state.type"
+      @closed="page.methods.onClosed"
+      :cover="page.state.cover"
+    />
+    <nut-cell
+      title="Text 文字提示"
+      is-link
+      @click="page.methods.openToast('text', '网络失败,请稍后再试~')"
+    ></nut-cell>
+    <nut-cell
+      title="Success 成功提示"
+      is-link
+      @click="page.methods.openToast('success', '成功提示')"
+    ></nut-cell>
+    <nut-cell
+      title="Error 失败提示"
+      is-link
+      @click="page.methods.openToast('fail', '失败提示')"
+    ></nut-cell>
+    <nut-cell
+      title="Warning 警告提示"
+      is-link
+      @click="page.methods.openToast('warn', '警告提示')"
+    ></nut-cell>
+    <nut-cell
+      title="Loading 加载提示"
+      is-link
+      @click="page.methods.openToast('loading', '加载中')"
+    ></nut-cell>
+    <nut-cell
+      title="Loading 带白色背景遮罩"
+      is-link
+      @click="page.methods.openToast('loading', '加载中', true)"
+    ></nut-cell>
+  </div>
+</template>
+
+<script lang="ts">
+import { reactive } from 'vue';
+export default {
+  setup() {
+    const page = {
+      state: reactive({
+        msg: 'toast',
+        type: 'text',
+        show: false,
+        cover: false
+      }),
+      methods: {
+        openToast: (type: string, msg: string, cover: boolean = false) => {
+          page.state.show = true;
+          page.state.msg = msg;
+          page.state.type = type;
+          page.state.cover = cover;
+        },
+        onClosed: () => console.log('closed')
+      }
+    };
+    return {
+      page
+    };
+  }
+};
+</script>
+
+<style lang="scss" scoped></style>