Browse Source

feat: overlay component

suzigang 5 years ago
parent
commit
ac92442af7
5 changed files with 381 additions and 407 deletions
  1. 282 271
      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

+ 282 - 271
src/config.js

@@ -1,378 +1,389 @@
 module.exports = {
-  "versions": [
+  versions: [
     {
-      "name": "1.x",
-      "link": "/1x/"
+      name: '1.x',
+      link: '/1x/'
     },
     {
-      "name": "2.x",
-      "link": "/"
+      name: '2.x',
+      link: '/'
     },
     {
-      "name": "3.x",
-      "link": "/3x/"
+      name: '3.x',
+      link: '/3x/'
     }
   ],
-  "header": [
+  header: [
     {
-      "name": "guide",
-      "cName": "指南",
-      "path": "/"
+      name: 'guide',
+      cName: '指南',
+      path: '/'
     },
     {
-      "name": "/",
-      "cName": "组件",
-      "path": "/"
+      name: '/',
+      cName: '组件',
+      path: '/'
     },
     {
-      "name": "example",
-      "cName": "示例",
-      "path": "/"
+      name: 'example',
+      cName: '示例',
+      path: '/'
     },
     {
-      "name": "resource",
-      "cName": "资源",
-      "path": "/resource"
+      name: 'resource',
+      cName: '资源',
+      path: '/resource'
     }
   ],
-  "docs": {
-    "name": "指南",
-    "packages": [
+  docs: {
+    name: '指南',
+    packages: [
       {
-        "name": "intro",
-        "cName": "介绍",
-        "show": true
+        name: 'intro',
+        cName: '介绍',
+        show: true
       },
       {
-        "name": "start",
-        "cName": "快速上手",
-        "show": true
+        name: 'start',
+        cName: '快速上手',
+        show: true
       },
       {
-        "name": "theme",
-        "cName": "主题定制",
-        "show": true
+        name: 'theme',
+        cName: '主题定制',
+        show: true
       },
       {
-        "name": "international",
-        "cName": "国际化",
-        "show": true
+        name: 'international',
+        cName: '国际化',
+        show: true
       },
       {
-        "name": "https://github.com/jdf2e/nutui/releases",
-        "cName": "更新日志",
-        "show": true,
-        "isLink": true
+        name: 'https://github.com/jdf2e/nutui/releases',
+        cName: '更新日志',
+        show: true,
+        isLink: true
       }
     ]
   },
-  "nav": [
+  nav: [
     {
-      "name": "布局组件",
-      "packages": [
+      name: '布局组件',
+      packages: [
         {
-          "name": "Button",
-          "sort": 1,
-          "cName": "按钮组件",
-          "type": "component",
-          "show": true,
-          "desc": "按钮用于触发一个操作,如提交表单。",
-          "author": "richard1015"
+          name: 'Button',
+          sort: 1,
+          cName: '按钮组件',
+          type: 'component',
+          show: true,
+          desc: '按钮用于触发一个操作,如提交表单。',
+          author: 'richard1015'
         },
         {
-          "name": "collapse",
-          "sort": 2,
-          "cName": "折叠面板",
-          "type": "component",
-          "show": true,
-          "desc": "折叠面板",
-          "author": "Ymm0008"
+          name: 'collapse',
+          sort: 2,
+          cName: '折叠面板',
+          type: 'component',
+          show: true,
+          desc: '折叠面板',
+          author: 'Ymm0008'
         },
         {
-          "name": "collapse",
-          "sort": 3,
-          "cName": "折叠面板-item",
-          "type": "component",
-          "show": false,
-          "desc": "折叠面板-item",
-          "author": "Ymm0008"
+          name: 'collapse',
+          sort: 3,
+          cName: '折叠面板-item',
+          type: 'component',
+          show: false,
+          desc: '折叠面板-item',
+          author: 'Ymm0008'
         },
         {
-          "name": "Layout",
-          "sort": 4,
-          "cName": "布局",
-          "type": "component",
-          "show": true,
-          "desc": "简便地创建布局",
-          "author": "undo"
+          name: 'Layout',
+          sort: 4,
+          cName: '布局',
+          type: 'component',
+          show: true,
+          desc: '简便地创建布局',
+          author: 'undo'
         },
         {
-          "name": "col",
-          "sort": 5,
-          "cName": "布局-Col",
-          "type": "component",
-          "show": false,
-          "desc": "布局组件Col",
-          "author": "undo"
+          name: 'col',
+          sort: 5,
+          cName: '布局-Col',
+          type: 'component',
+          show: false,
+          desc: '布局组件Col',
+          author: 'undo'
         },
         {
-          "name": "row",
-          "sort": 6,
-          "cName": "布局-Row",
-          "type": "component",
-          "show": false,
-          "desc": "布局组件Row",
-          "author": "undo"
+          name: 'row',
+          sort: 6,
+          cName: '布局-Row',
+          type: 'component',
+          show: false,
+          desc: '布局组件Row',
+          author: 'undo'
         }
       ]
     },
     {
-      "name": "操作反馈",
-      "packages": [
+      name: '操作反馈',
+      packages: [
         {
-          "name": "BackTop",
-          "sort": "1",
-          "cName": "回到顶部",
-          "type": "component",
-          "show": true,
-          "desc": "较长页面快捷回到顶部",
-          "author": "liqiong43"
+          name: 'BackTop',
+          sort: '1',
+          cName: '回到顶部',
+          type: 'component',
+          show: true,
+          desc: '较长页面快捷回到顶部',
+          author: 'liqiong43'
+        },
+        {
+          name: 'Toast',
+          sort: '1',
+          cName: '吐司',
+          type: 'component',
+          show: true,
+          desc: '轻提示',
+          author: 'undo'
         }
       ]
     },
     {
-      "name": "基础组件",
-      "packages": [
+      name: '基础组件',
+      packages: [
         {
-          "name": "Temp",
-          "sort": 1,
-          "cName": "模板组件",
-          "type": "component",
-          "show": true,
-          "desc": "组件模板示例",
-          "author": "richard1015"
+          name: 'Temp',
+          sort: 1,
+          cName: '模板组件',
+          type: 'component',
+          show: true,
+          desc: '组件模板示例',
+          author: 'richard1015'
         },
         {
-          "name": "Cell",
-          "sort": 1,
-          "cName": "单元格组件",
-          "type": "component",
-          "show": true,
-          "desc": "展示列表",
-          "author": "richard1015"
+          name: 'Cell',
+          sort: 1,
+          cName: '单元格组件',
+          type: 'component',
+          show: true,
+          desc: '展示列表',
+          author: 'richard1015'
         },
         {
-          "name": "Uploader",
-          "sort": 2,
-          "cName": "上传组件",
-          "type": "component",
-          "show": true,
-          "desc": "上传文件、图片",
-          "author": "richard1015"
+          name: 'Uploader',
+          sort: 2,
+          cName: '上传组件',
+          type: 'component',
+          show: true,
+          desc: '上传文件、图片',
+          author: 'richard1015'
         },
         {
-          "name": "Icon",
-          "sort": 3,
-          "cName": "图标组件",
-          "type": "component",
-          "show": true,
-          "desc": "图标",
-          "author": "richard1015"
+          name: 'Icon',
+          sort: 3,
+          cName: '图标组件',
+          type: 'component',
+          show: true,
+          desc: '图标',
+          author: 'richard1015'
         },
         {
-          "name": "Price",
-          "sort": 4,
-          "cName": "价格组件",
-          "type": "component",
-          "show": true,
-          "desc": "价格组件",
-          "author": "ailululu"
+          name: 'Price',
+          sort: 4,
+          cName: '价格组件',
+          type: 'component',
+          show: true,
+          desc: '价格组件',
+          author: 'ailululu'
         },
         {
-          "name": "Checkbox",
-          "sort": 5,
-          "cName": "复选按钮",
-          "type": "component",
-          "show": true,
-          "desc": "复选按钮",
-          "author": "Ymm0008"
+          name: 'Checkbox',
+          sort: 5,
+          cName: '复选按钮',
+          type: 'component',
+          show: true,
+          desc: '复选按钮',
+          author: 'Ymm0008'
         },
         {
-          "name": "Swiper",
-          "sort": 6,
-          "cName": "轮播",
-          "type": "component",
-          "show": true,
-          "desc": "轮播",
-          "author": "ailululu"
+          name: 'Swiper',
+          sort: 6,
+          cName: '轮播',
+          type: 'component',
+          show: true,
+          desc: '轮播',
+          author: 'ailululu'
         },
         {
-          "name": "Avatar",
-          "sort": 7,
-          "cName": "头像",
-          "type": "component",
-          "show": true,
-          "desc": "头像",
-          "author": "ailululu"
+          name: 'Avatar',
+          sort: 7,
+          cName: '头像',
+          type: 'component',
+          show: true,
+          desc: '头像',
+          author: 'ailululu'
         },
         {
-          "name": "Popup",
-          "sort": 8,
-          "cName": "弹出层",
-          "type": "component",
-          "show": true,
-          "desc": "弹出层容器,用于展示弹窗、信息提示等内容,支持多个弹出层叠加展示",
-          "author": "szg2008",
-          "version": "3.0.0"
+          name: 'Popup',
+          sort: 8,
+          cName: '弹出层',
+          type: 'component',
+          show: true,
+          desc:
+            '弹出层容器,用于展示弹窗、信息提示等内容,支持多个弹出层叠加展示',
+          author: 'szg2008',
+          version: '3.0.0'
         },
         {
-          "name": "Dialog",
-          "type": "component",
-          "cName": "对话框",
-          "desc": "模态对话框,在浮层中显示,引导用户进行相关操作,支持图片对话框。",
-          "sort": 8,
-          "show": true,
-          "author": "dsj"
+          name: 'Dialog',
+          type: 'component',
+          cName: '对话框',
+          desc:
+            '模态对话框,在浮层中显示,引导用户进行相关操作,支持图片对话框。',
+          sort: 8,
+          show: true,
+          author: 'dsj'
         },
         {
-          "version": "3.0.0",
-          "name": "Radio",
-          "type": "component",
-          "cName": "单选按钮",
-          "desc": "单选按钮",
-          "sort": 9,
-          "show": true,
-          "author": "Ymm0008"
+          version: '3.0.0',
+          name: 'Radio',
+          type: 'component',
+          cName: '单选按钮',
+          desc: '单选按钮',
+          sort: 9,
+          show: true,
+          author: 'Ymm0008'
         },
         {
-          "version": "3.0.0",
-          "name": "RadioGroup",
-          "type": "component",
-          "cName": "单选按钮组",
-          "desc": "单选按钮组",
-          "sort": 10,
-          "show": false,
-          "author": "Ymm0008"
+          version: '3.0.0',
+          name: 'RadioGroup',
+          type: 'component',
+          cName: '单选按钮组',
+          desc: '单选按钮组',
+          sort: 10,
+          show: false,
+          author: 'Ymm0008'
         },
         {
-          "version": "3.0.0",
-          "name": "CheckboxGroup",
-          "type": "component",
-          "cName": "多选按钮组",
-          "desc": "多选按钮组",
-          "sort": 11,
-          "show": false,
-          "author": "Ymm0008"
+          version: '3.0.0',
+          name: 'CheckboxGroup',
+          type: 'component',
+          cName: '多选按钮组',
+          desc: '多选按钮组',
+          sort: 11,
+          show: false,
+          author: 'Ymm0008'
         },
         {
-          "version": "3.0.0",
-          "name": "OverLay",
-          "type": "component",
-          "cName": "遮罩层",
-          "desc": "创建一个遮罩层,通常用于阻止用户进行其他操作",
-          "sort": 14,
-          "show": true,
-          "author": "szg2008"
+          version: '3.0.0',
+          name: 'OverLay',
+          type: 'component',
+          cName: '遮罩层',
+          desc: '创建一个遮罩层,通常用于阻止用户进行其他操作',
+          sort: 14,
+          show: true,
+          author: 'szg2008'
         }
       ]
     },
     {
-      "name": "导航组件",
-      "packages": [
+      name: '导航组件',
+      packages: [
         {
-          "name": "Navbar",
-          "sort": 3,
-          "cName": "导航组件",
-          "type": "componment",
-          "show": true,
-          "desc": "导航组件",
-          "author": "liqiong43"
+          name: 'Navbar',
+          sort: 3,
+          cName: '导航组件',
+          type: 'componment',
+          show: true,
+          desc: '导航组件',
+          author: 'liqiong43'
         },
         {
-          "name": "tab",
-          "sort": 1,
-          "cName": "标签组件",
-          "type": "component",
-          "show": true,
-          "desc": "标签组件",
-          "author": "zhenyulei"
+          name: 'tab',
+          sort: 1,
+          cName: '标签组件',
+          type: 'component',
+          show: true,
+          desc: '标签组件',
+          author: 'zhenyulei'
         },
         {
-          "name": "menu",
-          "sort": 2,
-          "cName": "菜单组件",
-          "type": "component",
-          "show": true,
-          "desc": "下拉菜单组件",
-          "author": "vickyYE"
+          name: 'menu',
+          sort: 2,
+          cName: '菜单组件',
+          type: 'component',
+          show: true,
+          desc: '下拉菜单组件',
+          author: 'vickyYE'
         },
         {
-          "name": "tabbar",
-          "sort": 2,
-          "cName": "标签栏组件",
-          "type": "component",
-          "show": true,
-          "desc": "标签栏组件",
-          "author": "Drjingfubo"
+          name: 'tabbar',
+          sort: 2,
+          cName: '标签栏组件',
+          type: 'component',
+          show: true,
+          desc: '标签栏组件',
+          author: 'Drjingfubo'
         }
       ]
     },
     {
-      "name": "数据录入",
-      "packages": [
+      name: '数据录入',
+      packages: [
         {
-          "name": "InputNumber",
-          "sort": 1,
-          "cName": "数字输入框",
-          "type": "component",
-          "show": true,
-          "desc": "数字输入框组件",
-          "author": "szg2008"
+          name: 'InputNumber',
+          sort: 1,
+          cName: '数字输入框',
+          type: 'component',
+          show: true,
+          desc: '数字输入框组件',
+          author: 'szg2008'
         },
         {
-          "name": "Input",
-          "sort": 2,
-          "cName": "输入框",
-          "type": "component",
-          "show": true,
-          "desc": "输入框组件",
-          "author": "gxx158"
+          name: 'Input',
+          sort: 2,
+          cName: '输入框',
+          type: 'component',
+          show: true,
+          desc: '输入框组件',
+          author: 'gxx158'
         },
         {
-          "version": "3.0.0",
-          "name": "Switch",
-          "type": "component",
-          "cName": "开关组件",
-          "desc": "用来打开或关闭选项",
-          "sort": 3,
-          "show": true,
-          "author": "zongyue3"
+          version: '3.0.0',
+          name: 'Switch',
+          type: 'component',
+          cName: '开关组件',
+          desc: '用来打开或关闭选项',
+          sort: 3,
+          show: true,
+          author: 'zongyue3'
         },
         {
-          "version": "3.0.0",
-          "name": "Rate",
-          "sort": 4,
-          "cName": "评分",
-          "type": "component",
-          "show": true,
-          "desc": "评分组件",
-          "author": "undo"
+          version: '3.0.0',
+          name: 'Rate',
+          sort: 4,
+          cName: '评分',
+          type: 'component',
+          show: true,
+          desc: '评分组件',
+          author: 'undo'
         },
         {
-          "version": "3.0.0",
-          "name": "Calendar",
-          "type": "component",
-          "cName": "日历",
-          "desc": "日历组件",
-          "sort": 5,
-          "show": true,
-          "author": ""
+          version: '3.0.0',
+          name: 'Calendar',
+          type: 'component',
+          cName: '日历',
+          desc: '日历组件',
+          sort: 5,
+          show: true,
+          author: ''
         }
       ]
     },
     {
-      "name": "业务组件",
-      "packages": []
+      name: '业务组件',
+      packages: []
     }
   ]
-};
+};

+ 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 => {