共计 5336 个字符,预计需要花费 14 分钟才能阅读完成。
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…
组件调用总结
调用非常不方便,使用需要导入,传入参数,回调之类的,不符合使用习惯,像 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…
封装总结
我是第一次封装自己的全局对象,Vue 原型挂载, vue.extend 的用法。官网 Vue.extend 说明 https://cn.vuejs.org/v2/api/i…
感觉还行的话,就去我那个项目点个 star 吧????
正文完