Vue 封裝Toast消息提示


Vue 封裝Toast消息提示

學習Vue的道路上,封裝一些自定義的組件不可避免,今天就來封裝一個Toast消息提示。后面還有dialog對話框,原理差不多。

首先先看看效果圖

現在才知道用qq錄制gif圖是真方便。(非廣告,后面會多用gif圖)

1 正常組件調用

在這里插入圖片描述

2 全局注冊對象調用(不知道是不是叫這個名字)

在這里插入圖片描述

一 首先,我們先封裝一個正常組件看看效果。

  • 1 首先創建一個最普通的組件/toast/Toast.vue 看看效果.
<template>
    <div class="Toast"
         v-if="showToast">
        {{ message }}
    </div>
</template>
<script>
    export default {
        name: "Toast",
        props: {
            showToast: {
                // 激活
                type: Boolean,
                default: false
            },
            message: {
                type: String,
                required: true
            },
            delay: {
                type: Number,
                default: 3000
            }
        },
        data() {
            return {
            }
        },
        methods: {
            // Toast消失
            disappear() {
                if (this.showToast) {
                    setTimeout(() => {
                        this.$emit("disappear");
                    }, this.delay)
                }
            },
        },
        watch: {
            showToast() {
                this.disappear()
            },
        },
    }
</script>

<style scoped>
    .Toast {
        position: fixed;
        left: 50%;
        top: 50%;
        background: rgb(233, 233, 235);
        padding: 10px;
        border-radius: 5px;
        transform: translate(-50%, -50%);
        animation: show-toast .2s;
        color: #909399;
        overflow: hidden;
        display: flex;
        align-items: center;
    }

    @keyframes show-toast {
        from {
            opacity: 0;
        }
        to {
            opacity: 1;

        }
    }
</style>

  • 2 調用看看效果

<template>
    <div>
        <toast
                :showToast="true"
                message="測試"
        />
    </div>

</template>

<script>
    import Toast from '@/components/common/toast/Toast'

    export default {
        name: 'Profile',
        data() {
            return {
            }
        },
        methods:{
            
        },
        components: {
            Toast,
           
        }
    }
</script>

<style scoped>
  

</style>

然后就能看到這樣的效果,但是樣式不夠好看。

在這里插入圖片描述

  • 3 稍微美化一下

我顏色搭配也沒什么經驗,就參考的ElementUI。

添加了type樣式, 還有提示的小圖標,共四種,需要自行去阿里矢量圖下載。

<template>
    <div class="Toast"
         :class="type"
         v-if="showToast">
        <span class="icon">
            <!--<img :src="iconSrc"/>-->
        </span>
        {{ message }}
    </div>
</template>

<script>
    /**
     * 自己封裝的Toast v0.1
     * params: showToast Boolean 是否激活toast 默認 false
     * params: type String       toast提示類型 共normal success,fail,warning 四個選項 默認normal
     * params: message String    toast消息
     * params: delay Number      toast顯示時間 默認 3000ms
     * */
    export default {
        name: "Toast",
        props: {
            showToast: {
                // 激活
                type: Boolean,
                default: false
            },
            type: {
                // 三種彈窗提示類型
                type: String,
                default: "normal"
            },
            message: {
                type: String,
                required: true
            },
            delay: {
                type: Number,
                default: 3000
            }
        },
        data() {
            return {
            }
        },
        methods: {
            // Toast消失
            disappear() {
                if (this.showToast) {
                    setTimeout(() => {
                        this.$emit("disappear");
                    }, this.delay)
                }
            },
        },
        watch: {
            showToast() {
                this.disappear()
            },
        },
        computed: {
            iconSrc() {
                // 這里使用的阿里矢量圖
                let tipType = ["normal", "success", "warning", "fail"];
                if (tipType.includes(this.type)) {
                    return require(`@/assets/img/common/${this.type}.svg`)
                } else {
                    throw "Toast type數據只允許為 normal, success, warning, fail 四種其中的一種,默認為normal"
                }
            }
        },


    }
</script>

<style scoped>
    .Toast {
        position: fixed;
        left: 50%;
        top: 50%;
        background: rgb(233, 233, 235);
        padding: 10px;
        border-radius: 5px;
        transform: translate(-50%, -50%);
        animation: show-toast .2s;
        color: #909399;
        overflow: hidden;
        display: flex;
        align-items: center;
    }

    @keyframes show-toast {
        from {
            opacity: 0;
        }
        to {
            opacity: 1;

        }
    }

    .success {
        color: #67C23A;
        background: rgb(225, 243, 216);
    }

    .warning {
        color: #E6A23C;
        background: rgb(250, 236, 216);
    }

    .fail {
        color: #F56C6C;
        background: rgb(253, 226, 226);
    }

    .icon img {
        width: 20px;
        height: 20px;
        margin-top: 3px;
        margin-right: 4px;
    }
</style>

  • 4 再看看美化后的效果, 有四種類型,就只看success類型的。

在這里插入圖片描述

對應完整代碼Github地址 https://github.com/CoderCharm/Mall/blob/master/src/components/common/toast/Toast.vue

組件調用總結

調用非常不方便,使用需要導入,傳入參數,回調之類的,不符合使用習慣,像ElementUI那種,使用起來就特別方便。
下一步就是超那個方向封裝。

二 組件封裝全局注冊

  • 1 這次重新創建一個/toast/CustToast.vue組件,里面就不怎么寫邏輯.
<template>

    <div class="CustToast"
         :class="type"
         v-if="showToast">

        <span class="icon">
            <img :src="iconSrc"/>
        </span>

        {{ message }}
    </div>

</template>

<script>
    export default {
        /**
         * 自己封裝的Toast v0.2
         * params: showToast Boolean 是否激活toast 默認 false
         * params: type String       toast提示類型 共normal success,fail,warning 四個選項 默認normal
         * params: message String    toast消息
         * params: duration Number      toast顯示時間 默認 3000ms
         * */
        name: "CustToast",
        data() {
            return {
                showToast: true,
                type: "normal",
                message: "消息提示",
                duration: 3000
            }
        },
        computed: {
            iconSrc() {
                window.console.log("當前類型", this.type);
                let tipType = ["normal", "success", "warning", "fail"];
                if (tipType.includes(this.type)) {
                    return require(`@/assets/img/common/${this.type}.svg`)
                } else {
                    throw "Toast type數據只允許為 normal, success, warning, fail 四種其中的一種,默認為normal"
                }
            }
        },
    }
</script>

<style scoped>
    .CustToast {
        position: fixed;
        left: 50%;
        top: 50%;
        background: rgb(233, 233, 235);
        padding: 10px;
        border-radius: 5px;
        transform: translate(-50%, -50%);
        animation: show-toast .2s;
        color: #909399;
        overflow: hidden;
        display: flex;
        align-items: center;
    }

    @keyframes show-toast {
        from {
            opacity: 0;
        }
        to {
            opacity: 1;
        }
    }

    .success {
        color: #67C23A;
        background: rgb(225, 243, 216);
    }

    .warning {
        color: #E6A23C;
        background: rgb(250, 236, 216);
    }

    .fail {
        color: #F56C6C;
        background: rgb(253, 226, 226);
    }

    .icon img {
        width: 20px;
        height: 20px;
        margin-top: 3px;
        margin-right: 4px;
    }

</style>

  • 2 然后在同級目錄創建/toast/index.js文件組冊,給Vue添加原型$toast
//
import vue from 'vue'

// 導入自定義到Toast組件
import CustToast from './CustToast.vue'


// 生成一個擴展實例構造器
const ToastConstructor = vue.extend(CustToast);

// 定義彈出組件的函數 接收三個參數 消息 toast類型 顯示時間
function showToast(message, type="normal", duration = 2000) {

    // 實例化一個 CustToast.vue
    const _toast = new ToastConstructor({
        data() {
            return {
                showToast: true,
                type: type,
                message: message,
                duration: duration
            }
        }
    });

    // 把實例化的 CustToast.vue 添加到 body 里
    let element = _toast.$mount().$el;
    document.body.appendChild(element);

    // duration時間到了后隱藏
    setTimeout(() => {_toast.showToast = false} ,duration)
}

// 需要在main.js 里面使用 Vue.use(showToast);
showToast.install = (Vue) => {
    // 將組件注冊到 vue 的 原型鏈里去,
    // 這樣就可以在所有 vue 的實例里面使用 this.$toast()
    Vue.prototype.$toast = showToast
};

// 導出
export default showToast
  • 3 vue-cli main.js文件注冊
import showToast from '@/你的路徑/toast/index'

Vue.use(showToast);
  • 4 使用
// 封裝的時候, 定義了三個參數,message必須要傳
// message, type="normal", duration = 2000

this.$toast("測試普通")
this.$toast("測試成功", "success", 5000)
this.$toast("測試警告", "warning")
this.$toast("測試失敗", "fail")

就可以看到開頭,我那個演示的gif了。

當然呢,消息提示顯示的位置,我沒自定義統一顯示在中間,同樣是按照type一樣的思路,給個class樣式就可以了。
還有就消失的動畫沒處理,多個消息彈出的時候直接折疊了。

第二個封裝樣式Github地址: https://github.com/CoderCharm/Mall/blob/master/src/components/common/toast/CustToast.vue

封裝總結

我是第一次封裝自己的全局對象,Vue原型掛載, vue.extend的用法。官網Vue.extend說明https://cn.vuejs.org/v2/api/index.html#Vue-extend

感覺還行的話,就去我那個項目點個star吧🤩


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM