基于 rmc-notification 实现移动端 Toast

2,896 阅读2分钟

背景

最近在用 react 做移动端的时候需要一个消息提示的组件,然后我们的 ui 库是用的 MATERIAL-UI ,然后发现 antd-moblie Toast 不错。虽然可以用antd mobile 的组件并且只需要配置按需加载并不会增大多少打包体积,但是总感觉下一个库就用一个组件有点浪费,所以决定自己造个轮子

成品

rmc-notification

我把 antd-moblie 下载完以后阅读他的源代码,发现他是依赖了一个 rc 系列的一个库 rmc-notification。接下来干啥呢

npm instsall

发现报错了缺少 rc-animate,继续 npm i rc-animate --save

运行

运行起来以后基础组件长这样 先不管丑不丑看看直接看 api 好不好用

基础版

文档写的简单,功能也简单

var Notification = require('rmc-notification');
Notification.newInstance({}, notification => {
  notification.notice({
    content: 'content'
  });
});

升级版

官方的例子解锁更多的姿势

import 'rmc-notification/assets/index.css';
import Notification from 'rmc-notification';
import React from 'react';
import ReactDOM from 'react-dom';
let notification = null;
Notification.newInstance({}, (n) => notification = n);

function simpleFn() {
  notification.notice({
    content: <span>simple show</span>,
    onClose() {
      console.log('simple close');
    },
  });
}

function durationFn() {
  notification.notice({
    content: <span>can not close...</span>,
    duration: null,
  });
}

function closableFn() {
  notification.notice({
    content: <span>closable</span>,
    duration: null,
    onClose() {
      console.log('closable close');
    },
    closable: true,
  });
}

function close(key) {
  notification.removeNotice(key);
}

function manualClose() {
  const key = Date.now();
  notification.notice({
    content: <div>
      <p>click below button to close</p>
      <button onClick={close.bind(null, key)}>close</button>
    </div>,
    key,
    duration: null,
  });
}

看完以后发现满足自己的功能了我们先改造起来

美化

设计

  • 普通提示
  • 成功提示
  • 失败提示
  • loaing
  • 配置

封装

先写一个基础类

 class Toast {
    duration = 2;
    loadingText = '努力加载中';
    config(c) {
    }
    info(tip, duration) {
        
    }
    success(tip, duration) {
       
    }
    fail(tip, duration) {
    }
    loading(loadingText) {
    }
    hide() {
    }

然后开始填充基础的代码, loading 比较特殊最好考虑

class Toast {
    duration = 2;
    loadingText = '努力加载中';
    config(c) {
        this.duration = c.duration;
        this.loadingText = c.loadingText;
    }
    info(tip, duration) {
        notification.notice({
            content: <div className="toast_body">{tip}</div>,
            duration,
        });
    }
    success(tip, duration) {
        notification.notice({
            content: (
                <div className="toast_body">
                    <CheckIcon className="toast_success" />
                    <div className="toast_tip">{tip}</div>
                </div>
            ),
            duration: duration || this.duration,
        });
    }
    fail(tip, duration) {
        notification.notice({
            content: (
                <div className="toast_body">
                    <FailIcon className="toast_success" />
                    <div className="toast_tip">{tip}</div>
                </div>
            ),
            duration: duration || this.duration,
        });
    }
    loading(loadingText) {
       
    }
    hide() {
    }
}

loading

loading 比较特殊的原因是因为它的场景和其他的不一样,其他的是几秒内就消失了。loading 他要等待请求结束才消失,而 rmc-notification 提供的让 Toast 消失的 api是要有一个唯一key, 所以我们这么写

loading(loadingText) {
        const key = Date.now();
        this.key = key;
        notification.notice({
            content: (
                <div className="toast_body">
                    <LoadingIcon className="toast_loading" spin rotate={90} />
                    <div className="toast_tip">{loadingText || this.loadingText}</div>
                </div>
            ),
            duration: null,
            key,
        });
    }
    hide() {
        notification.removeNotice(this.key);
    }

css 部分

.rmc-notification-notice {
    background: rgba(58, 58, 58, 0.9);
    padding: 7px 10px;
}

.rmc-notification-notice-content {
    color: #fff !important;
    font-family: "Roboto", "Helvetica", "Arial", sans-serif;
    font-size: 0.875rem;
    font-weight: 200;
}

.toast_success {
    font-weight: 200;
    font-size: 2.25rem;
    display: block;
}
.toast_body {
    display: flex;
    flex-direction: column;
    align-items: center;
}
.toast_loading {
    font-size: 2.25rem;
    width: 2.25rem;
    height: 2.25rem;
     display: inline-block;
    -webkit-transform: rotate(360deg);
    -moz-animation: rotation 1s linear infinite;
    -webkit-animation: rotation 1s linear infinite;
    -o-animation: rotation 1s linear infinite;

}
.toast_tip {
    margin-top: 0.375rem;
}
@-webkit-keyframes rotation {
    from {
        -webkit-transform: rotate(0deg);
    }

    to {
        -webkit-transform: rotate(360deg);
    }
}

最后

到这里就已经满足基础需求了,还有更多的功能就需要自己加了,当然我的代码也有很多优化空间,不过本文的目的是安利 rmc-notification 这个库,毕竟 REACT 不像 VUE那么多组件库。ღ( ´・ᴗ・` )比心