第一次写文章,不喜少喷😅,最好不喷,哈哈哈。若有错误,还请大佬提出,🙏🙏前端
做为一个前端开发,开发调试中console.log()
还有alert()
,不能再熟悉了,要是想在页面输出一个弹框,不能一直alert()
吧,太反人类了,做为直男审美的我都接受不了,其实公司封装好了一个toast组件,可是最近在弄本身的毕业设计,就想本身也封装一个吧,😂就是想本身折腾折腾,绝对不是为了kpi!!! 第一个图是alert()
,微信端还有手机浏览器都不同,总之调试的时候无所谓,可是想上线或者一个完整的项目,弹框确定是有的,那就动手撸一个吧。 vue
Toast.vue命名习惯很重要,以前一直被吐槽,组件仍是首字母大写吧。一个好的编程习惯可让你更好的进行团队开发,尤为是codeReview的时候。编程
<template>
<div class="toast-item">hello world !</div>
</template>
<script>
export default {
name: 'Toast'
</script>
<style scoped>
.toast-item {
margin-bottom: 15px;
padding: 10px 20px;
line-height: 25px;
color: #FFF;
background-color: rgba(0, 0, 0, .9);
border-radius: 5px;
transition: all .3s;
}
</style>
复制代码
这就是一个普通的vue文件,在使用的地方注册一下,就能看到页面,调整样式,这里就不用多说了。浏览器
以前看到一篇文章,每次弹窗都会在body后添加一个新的div,感受性能不是很好,我使用这个文件,将toast的值传进来,这样就只添加一个div,只是改变div的内容bash
<template>
<transition-group tag="div" class="toast-list" name="toast" v-bind="options">
<toast-item v-for="toast in toasts" :key="toast.message" v-bind="toast" @remove="remove(toast)" />
</transition-group>
</template>
<script>
import ToastItem from './Toast'
export default {
name: 'ToastList',
components: { ToastItem },
props: ['options'],
data () {
return {
toasts: []
}
},
created () {
document.body.appendChild(this.$mount().$el)
},
destroyed () {
document.body.removeChild(this.$el)
},
methods: {
add (toast = {}) {
const { message } = toast
if (
message &&
this.toasts.every(item => item.message !== message)
) {
this.toasts.push(toast)
}
},
remove (toast) {
this.toasts = this.toasts.filter(item => item !== toast)
}
}
}
</script>
<style scoped>
.toast-list {
position: fixed;
top: 50px;
left: 0;
z-index: 9999;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
pointer-events: none;
}
.toast-enter, .toast-leave-to {
opacity: 0;
transform: translate3d(0, -5px, 0);
}
.toast-leave-active {
position: absolute;
}
</style>
复制代码
toast弹出的文字是须要动态传进来的,因此,把以前的Toast.vue文件修改一下微信
<template>
<div class="toast-item">{{ message }}</div>
</template>
<script>
export default {
name: 'Toast',
props: {
message: String,
duration: {
type: Number,
default: 2000
}
},
mounted () {
if (this.duration) {
setTimeout(() => this.$emit('remove'), this.duration)
}
}
}
</script>
<style scoped>
.toast-item {
margin-bottom: 15px;
padding: 10px 20px;
line-height: 25px;
color: #FFF;
background-color: rgba(0, 0, 0, .9);
border-radius: 5px;
transition: all .3s;
}
</style>
复制代码
刚刚只是写的一个静态的vue文件,但是这并非咱们须要的效果,如今的需求是动态加载这个组件 在当前目录新建一个index.js(和Toast.vue等同级),直接放代码了 为了是组件能够复用,样式就不能写死,尤为是面对不一样的甲方爸爸,有时候只要改个背景色,有时候改个位置,那就设置一个属性toast.listOptions
专门来调整样式吧app
import Vue from 'vue'
import ToastList from './ToastList'
let toastList
function toast (arg) {
if (!toastList) {
toastList = new Vue({
extends: ToastList,
propsData: {
options: toast.listOptions
}
})
}
const toastItem = typeof arg === 'string'
? { message: arg }
: arg
toastList.add(toastItem)
}
toast.listOptions = {}
//注意这边export出来的是toast
export default toast
复制代码
到这里,咱们已经基本上完成了一个能够全局注册和动态加载的toast组件,只须要在页面中import一下性能
import toast from '../components/toast/index.js'
toast('Error !')
// custom options
toast({
message: 'Error !',
// auto close after 2000ms
duration: 2000,
//change style
style: {
color: '#F56C6C',
background: '#FEF0F0',
border: '1px solid #FDE2E2'
}
})
复制代码