手写一个基于vue的全局Toast组件吧
2019-05-12 本文已影响1人
小鳄鱼的大哥哦
目标文件components/toast
文件夹
main.js
import Vue from "vue";
import Main from "./main.vue"; // 引入toast 组件
// extent方法传入一个vue组件,生成一个子实例对象
// 要求组件中的data必须是函数,也就是为什么我们的组件中的data必须是函数
let ToastConstructor = Vue.extend(Main);
let instance;
const Toast = function (options = {
content: '', // 必传参数
duration: 3000 // 显示时间
}) {
// 渲染成Vue组件
instance = new ToastConstructor({
data: options // 这里的 data 会传到 main.vue 组件中的 data 中,当然也可以写在 props 里
});
// instance.$el是生成的DOM对象,添加到body中
document.body.appendChild(instance.$mount().$el);
};
// 以下就是在 Toast 函数中拓展 ["success", "error"] 这两个方法
let tostTypes = ["success", "error"]
tostTypes.forEach(type => {
Toast[type] = options => {
options.type = type;
return Toast(options);
};
});
// 调用方法this.$Toast.success()...
export default Toast;
main.vue
<template>
<div class="toast" :class="type ? `toast--${type}` : ''">
<p>{{content}}</p>
</div>
</template>
<script>
export default {
name: "Toast",
data(){
return{
content: '',
duration: '',
type:'',
}
},
mounted() {
setTimeout(() => {
// 3s 后通过父级移除子元素的方式来移除该组件实例和 DOM 节点
this.$destroy(true);
this.$el.parentNode.removeChild(this.$el);
}, this.duration);
}
};
</script>
<style lang="scss" scoped>
.toast {
display: flex;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
color: #fff;
z-index: 9999;
background: transparent;
> p {
padding: 12px 22px;
font-size: 18px;
border-radius: 4px;
background: rgba(17, 17, 17, 0.7);
}
// error和success的样式
&--error p { background: rgba(255, 0, 0, 0.5); }
&--success p { background: rgba(0, 255, 0, 0.5); }
}
</style>
根目录下的main.js
import Vue from 'vue'
import Toast from './components/toast/main'
Vue.prototype.$toast = Toast
组建中使用
this.$toast({content: '网络错误',duration: 3000})
this.$toast.success({content: '网络错误',duration: 3000})
this.$toast.error({content: '网络错误',duration: 3000})