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吧🤩