开发一个UI框架项目[6]-Toast

本文最后更新于:2020年9月29日 晚上

设计细节

  1. 兼容性设计。在设计关闭提示框按钮的时候,有考虑要如何实现:如果是一个关闭图标,在移动端的交互体验会有点差,因为图标太小,手指有可能很难点击命中;所以将关闭区域设置得稍微大一点,在提示文案的右边区域作为关闭点击区域,同时支持设置点击回调函数。
  2. 方向设置。可设置提示框的弹出方向,按时钟顺序包括:上、右、下、左、中。
  3. 自动关闭。可设置自动关闭以及关闭的时间。

功能设计

  1. 开发为插件。对于toast的定位就是有点击等操作时可以通过this.$toast直接调用toast,一开始的想法是直接在Vue.prototype上添加,但是这种方案有弊端,就是无法确定Vue.prototype.$toast能不能直接用,会不会已经被用户设置成其它的,所以这样的修改的决定权还是得交给用户,因此我们可以采用vue的插件机制来完成这件事情:

    1
    2
    3
    4
    5
    6
    7
    export default {
    install(Vue, options) {
    Vue.prototype.$toast = function(toastOptions) {
    // ...
    }
    }
    }
  2. 动态创建。使用this.$toast的时候可以生成toast组件,包含了指定的内容,然后挂载到页面中,同时还要兼容处理页面中同时只能有一个toast,如果生成之前已经有了toast组件,需要先销毁:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    // plugin.js
    let currentToast

    export default {
    install(Vue, options) {
    Vue.prototype.$toast = function(toastOptions) {
    if (currentToast) {
    currentToast.onClose()
    }
    currentToast = createToast({
    Vue,
    propsData: toastOptions,
    onClose: () => {
    currentToast = null
    }
    })
    }
    }
    }

    function createToast({ Vue, propsData, onClose }) {
    const Constructor = Vue.extend(Toast)
    const toast = new Constructor({ propsData })
    toast.$slots.default = [propsData.message]
    toast.$mount()
    toast.$on('close', onClose)
    document.body.appendChild(toast.$el)
    return toast
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <!-- Toast.vue -->
    <script>
    export default {
    name: "YvToast",
    methods: {
    // ...
    onClose() {
    this.$el.remove()
    this.$emit('close')
    this.$destroy()
    }
    }
    }
    </script>
  3. 设置toast出现动画。这里有个坑,就是toast 动画中的属性 transform: translate() 在使用了 fixed 绝对定位后与 transform: translate() 发生了冲突,解决方案是在toast外套一层wrapper负责fixed定位,toast自身负责动画:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    @keyframes pushToast-top {
    0% {opacity: 0;transform: translateY(-100%)}
    100% {opacity: 1;transform: translateY(0)}
    }
    @keyframes pushToast-bottom {
    0% {opacity: 0;transform: translateY(100%)}
    100% {opacity: 1;transform: translateY(0)}
    }
    @keyframes pushToast-middle {
    0% {opacity: 0;}
    100% {opacity: 1;}
    }
    @keyframes pushToast-left {
    0% {opacity: 0;transform: translateX(-100%)}
    100% {opacity: 1;transform: translateY(0)}
    }
    @keyframes pushToast-right {
    0% {opacity: 0;transform: translateX(100%)}
    100% {opacity: 1;transform: translateY(0)}
    }

    .wrapper {
    position: fixed;
    z-index: 9999;
    &.toast-position-top {
    left: 50%;
    top: 10px;
    transform: translateX(-50%);
    .yv-toast {
    animation: pushToast-top .3s;
    }
    }
    &.toast-position-right {
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    .yv-toast {
    animation: pushToast-right .3s;
    }
    }
    &.toast-position-bottom {
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
    .yv-toast {
    animation: pushToast-bottom .3s;
    }
    }
    &.toast-position-left {
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    .yv-toast {
    animation: pushToast-left .3s;
    }
    }
    &.toast-position-middle {
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    .yv-toast{
    animation: pushToast-middle 1s;
    }
    }
    }

人工测试

手动测试。。。已完成。

自动化测试

未完成。

vuepress设置

docs/.vuepress/components文件夹下增加toast-basictoast-closevue文件,内容就是我们要展示的toast示例,然后在docs/components文件夹下增加toast的md文件,内容就是放置整个toast组件说明。

具体内容请访问这里


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!