浏览代码

feat: toast组件开发

songqibin 5 年之前
父节点
当前提交
2b8621f772
共有 5 个文件被更改,包括 108 次插入136 次删除
  1. 9 0
      src/config.js
  2. 4 2
      src/packages/toast/demo.vue
  3. 28 107
      src/packages/toast/doc.md
  4. 15 8
      src/packages/toast/index.vue
  5. 52 19
      src/packages/toast/toast.ts

+ 9 - 0
src/config.js

@@ -137,6 +137,15 @@ module.exports = {
           show: true,
           desc: '较长页面快捷回到顶部',
           author: 'liqiong43'
+        },
+        {
+          name: 'Toast',
+          sort: '1',
+          cName: '吐司',
+          type: 'component',
+          show: true,
+          desc: '轻提示',
+          author: 'undo'
         }
       ]
     },

+ 4 - 2
src/packages/toast/demo.vue

@@ -52,8 +52,10 @@ export default createDemo({
       Toast.warn(msg);
     };
     const loadingToast = msg => {
-      Toast.loading(msg, { duration: 0 });
-      setTimeout(Toast.hide, 3000);
+      Toast.loading(msg, { duration: 0, id: 'test' });
+      setTimeout(() => {
+        Toast.success('加载完成', { id: 'test', duration: 2000 });
+      }, 2000);
     };
     return {
       textToast,

+ 28 - 107
src/packages/toast/doc.md

@@ -2,154 +2,75 @@
 
 轻提示。
 
-## 基本用法
-文字提示
-```javascript
-export default {
-  mounted() {
-    this.$toast.text('提示信息');
-  }
-}
-```
+### 介绍
 
-成功提示
+用于轻提示。
 
-```javascript
-export default {
-  mounted() {
-    this.$toast.success('操作成功!');
-  }
-}
+### 安装
+
+``` javascript
+import { createApp } from 'vue';
+import { Toast } from '@nutui/nutui';
+
+const app = createApp();
+app.use(Toast);
 ```
 
-失败提示
+## 代码演示
+
+### 基本用法
 
+文字提示
 ```javascript
-export default {
-  mounted() {
-    this.$toast.fail('操作失败!');
-  }
-}
+Toast.text(msg);
 ```
 
-警告提示
+成功提示
 
 ```javascript
-export default {
-  mounted() {
-    this.$toast.warn('确定删除?');
-  }
-}
+Toast.success(msg);
 ```
 
-## 加载提示
+失败提示
 
 ```javascript
-// 带文案,显示透明遮罩层(默认),自动消失
-this.$toast.loading('加载中...',{ 
-    duration:3000
-});
-
-//带文案,显示半透明遮罩层,自动消失,点击遮罩层后消失
-this.$toast.loading('加载中...',{ 
-    duration:3000,
-    coverColor: "rgba(0,0,0,0.5)",
-    closeOnClickOverlay: true
-});
-
-//不会自动消失(默认),不带遮罩层
-this.loading = this.$toast.loading({
-    cover: false
-});
-
-//手动关闭上面的Loading
-this.loading.hide();
+Toast.fail(msg);
 ```
 
-## 自定义样式
+警告提示
 
 ```javascript
-//自定义背景颜色/透明度
-this.$toast.text('自定义背景颜色/透明度',{
-    bgColor:'rgba(50, 50, 50, 0.9)'
-});
-
-//自定义class
-this.$toast.text('自定义class',{
-    customClass:'my-class'
-});
-
-//自定义Icon
-this.$toast.text('自定义Icon',{
-    icon:"https://img13.360buyimg.com/imagetools/jfs/t1/98294/28/14470/22072/5e65ba08E865683aa/ded7441bdd098511.png"
-});
+Toast.warn(msg);
 ```
-## 共享实例
 
-如果不设置id,多个Toast将默认拥有相同的id,**它们将共享一个实例**(loading类型与其他类型实例不共享),新的内容和设置将取代旧的,多个Toast不能同时出现。如果不需要共享实例,可以给其设置id。
+### 动态更新
 
 ```javascript
-//二者id不同,不会共享一个实例
-this.$toast.success(msg,{
-    id:123
-});
-
-this.$toast.text(msg,{
-    id:321,
-    duration:4000
-});
+Toast.loading(msg, { duration: 0, id: 'test' });
+setTimeout(() => {
+  Toast.success('加载完成', { id: 'test', duration: 2000 });
+}, 2000);
 ```
 
-## 支持在JS模块中导入使用
+##¥ 支持在JS模块中导入使用
 ```javascript
 import { Toast } from "@nutui/nutui";
-
 Toast.text('在js模块中使用');
 // 返回实例,可以手动调用实例中的hide方法关闭提示
 const toast = Toast.loading('在js模块中使用');
 toast.hide();
 ```
 
-## 修改默认配置
-
-通过**Toast.setDefaultOptions**函数可以全局修改 Toast 的默认配置,**值得注意的是,loading无法支持默认配置的修改和重置**。
-
-```js
-// 更改所有Toast展示时长设置为5000毫秒
-Toast.setDefaultOptions({
-    duration: 5000,
-    coverColor: "rgba(0, 0, 0, 0.2)",
-    closeOnClickOverlay: true,
-    cover: true
-});
-
-// 重置所有 Toast 的默认配置
-Toast.resetDefaultOptions();
-
-// 更改所有文字提示默认设置
-Toast.setDefaultOptions("text", {
-    size: "large",
-    cover: true,
-    coverColor: "rgba(0, 0, 0, 0.2)",
-    duration: 3000,
-    closeOnClickOverlay: true
-});
-
-// 重置 text Toast 的默认配置
-Toast.resetDefaultOptions("text");
-```
 
 ### API
 | 方法名                    | 说明                                                                    | 参数            | 返回值     |
 | ------------------------- | ----------------------------------------------------------------------- | --------------- | ---------- |
 | Toast.text                | 展示文字提示                                                            | options/message | toast 实例 |
-| Toast.loading             | 展示加载提示                                                            | options/message | toast 实例 |
 | Toast.success             | 展示成功提示                                                            | options/message | toast 实例 |
 | Toast.fail                | 展示失败提示                                                            | options/message | toast 实例 |
 | Toast.warn                | 展示警告提示                                                            | options/message | toast 实例 |
 | Toast.hide                | 关闭提示                                                                | force:boolean   | void       |
-| Toast.setDefaultOptions   | 修改默认配置,对所有 Toast 生效<br>传入 type 可以修改指定类型的默认配置 | type/options    | void       |
-| Toast.resetDefaultOptions | 重置默认配置,对所有 Toast 生效<br>传入 type 可以重置指定类型的默认配置 | type            | void       |
+| Toast.loading             | 展示加载提示                                                            | options/message | toast 实例 |
 
 ## Options
 

+ 15 - 8
src/packages/toast/index.vue

@@ -90,13 +90,11 @@ export default create({
   },
   setup(props) {
     console.log('props', props);
-    const state = reactive({
-      timer: null
-    });
+    let timer;
     const clearTimer = () => {
-      if (state.timer) {
-        clearTimeout(state.timer);
-        state.timer = null;
+      if (timer) {
+        clearTimeout(timer);
+        timer = null;
       }
     };
     const hide = () => {
@@ -107,7 +105,7 @@ export default create({
     const show = () => {
       clearTimer();
       if (props.duration) {
-        state.timer = setTimeout(() => {
+        timer = setTimeout(() => {
           hide();
         }, props.duration);
       }
@@ -123,6 +121,15 @@ export default create({
       show();
     }
 
+    watch(
+      () => props.duration,
+      val => {
+        if (val) {
+          show();
+        }
+      }
+    );
+
     const hasIcon = computed(() => {
       console.log(props.type);
       if (props.type !== 'text') {
@@ -143,7 +150,7 @@ export default create({
       ];
     });
     return {
-      state,
+      hide,
       clickCover,
       hasIcon,
       toastBodyClass

+ 52 - 19
src/packages/toast/toast.ts

@@ -1,10 +1,10 @@
-import { createVNode, render, App } from 'vue';
+import { createVNode, defineComponent, render, App } from 'vue';
 import VueToast from './index.vue';
-
+const ToastConstructor = defineComponent(VueToast);
 const defaultOptions = {
   msg: '',
   id: '',
-  visible: false,
+  visible: true,
   duration: 2000, //显示时间(毫秒)
   center: true,
   type: 'text',
@@ -22,33 +22,66 @@ const defaultOptions = {
   closeOnClickOverlay: false
 };
 
-let currentOptions = {
-  ...defaultOptions
+let idsMap: string[] = [];
+let optsMap: any[] = [];
+const clearToast = (id?: string) => {
+  if (id) {
+    const container = document.getElementById(id);
+    optsMap = optsMap.filter(item => item.id !== id);
+    idsMap = idsMap.filter(item => item !== id);
+    if (container) {
+      document.body.removeChild(container);
+    }
+  } else {
+    idsMap.forEach(item => {
+      const container = document.getElementById(item);
+      if (container) {
+        document.body.removeChild(container);
+      }
+    });
+    optsMap = [];
+    idsMap = [];
+  }
 };
 
-const clearToast = (id = currentOptions.id) => {
-  const container = document.getElementById(id);
+const updateToast = opts => {
+  const container = document.getElementById(opts.id);
   if (container) {
-    document.body.removeChild(container);
+    const currentOpt = optsMap.find(item => item.id === opts.id);
+    if (currentOpt) {
+      opts = { ...defaultOptions, ...currentOpt, ...opts };
+    } else {
+      opts = { ...defaultOptions, ...opts };
+    }
+    const instance: any = createVNode(ToastConstructor, opts);
+    render(instance, container);
+    return instance.component.ctx;
   }
 };
 
 const mountToast = opts => {
-  // checkExitToast();
-  opts = { ...defaultOptions, ...opts };
-  opts.visible = true;
   opts.unmount = clearToast;
-  opts.id = new Date().getTime() + '';
-  console.log(opts);
-  currentOptions = { ...opts };
-
+  let _id;
+  // 如果是更新已有的toast
+  if (opts.id) {
+    _id = opts.id;
+    if (idsMap.find(item => item === opts.id)) {
+      return updateToast(opts);
+    }
+  } else {
+    _id = new Date().getTime() + '';
+  }
+  opts = { ...defaultOptions, ...opts };
+  opts.id = _id;
+  idsMap.push(opts.id);
+  optsMap.push(opts);
   const container = document.createElement('div');
   container.id = opts.id;
-  const vm = createVNode(VueToast, opts);
-  render(vm, container);
+  const instance: any = createVNode(ToastConstructor, opts);
+  render(instance, container);
   document.body.appendChild(container);
-  console.log(vm);
-  return vm;
+  console.log(instance.component);
+  return instance.component.ctx;
 };
 
 const errorMsg = msg => {