写了两三天, 终于把 toast 组件写出来了. 不敢说是最好的设计, 希望有更好思路的朋友可以在评论区给我意见!_(:з)_
第一步: 写 toast.vue, 将样式之类的先定下来
- <template>
- <div v-show="showToast" class="toast" :class="position">
- <div class="toast_container" v-if="type=='success'">
- <div><i class="iconfont icon-check icon"></i></div>
- <div class="msg_container">{{message}}</div>
- </div>
- <div class="toast_container" v-else-if="type=='wrong'">
- <div><i class="iconfont icon-warning-circle icon"></i></div>
- <div class="msg_container">{{message}}</div>
- </div>
- <div class="toast_container" v-else-if="type=='loading'">
- <div><loading10></loading10></div>
- <div class="msg_container">{{message}}</div>
- </div>
- </div>
- </template>
- <script>
- import loading10 from '../loading/spiner'
- export default{
- props:{
- message:String,
- type:{
- validator: function (value) {
- // 值必须是这些字符串中的一个
- return ['success', 'wrong', 'loading'].indexOf(value) !== -1
- },
- default:'success'
- },
- duration:{
- type:Number,
- default:3000
- },
- position:{
- type:String,
- default:'middle'
- }
- },
- components:{
- loading10
- },
- data(){
- return{
- showToast:false
- }
- }
- }
- </script>
- <style scoped>
- .toast{
- width:100%;
- }
- .toast_container{
- background: rgba(0, 0, 0, 0.7);
- border-radius: 8px;
- color:#fff;
- margin-left:88px;
- margin-right:88px;
- text-align:center;
- padding-top:15px;
- padding-bottom: 15px;
- }
- .top{
- position:absolute;
- top:10%;
- }
- .middle{
- position:absolute;
- top:40%;
- }
- .bottom{
- position:absolute;
- top:70%;
- }
- .msg_container{
- margin-top:8px;
- margin-left:15px;
- margin-right:15px;
- line-height: 22px;
- font-size: 16px;
- word-wrap: break-word;
- }
- .icon{
- font-size:30px;
- }
- </style>
一共三种样式, 成功(success), 失败(wrong), 加载中(loading);
一共三种位置, 上(top), 中(middle), 下(bottom);
所有涉及的图案出自阿里的 iconfont 手机淘宝图标库.
加载中动画是自己写的蹩脚的加载组件(emmm, 就不放出来污染大家眼睛了, 需要的可以评论区知会一声_(:з)_)
第二步: 写 index.js , 完成 toast 组件的实例化
- import Vue from 'vue'
- import Toast from './toast'
- let singleToast=true;
- let queue=[];
- function createInstance(){
- // 返回一个扩展实例构造器
- if(!queue.length||!singleToast){
- const ToastConstructor = Vue.extend(Toast);
- // 构造一个实例
- const toastDom = new ToastConstructor({
- el: document.createElement('div'),
- });
- // 把实例化的 toast.vue 添加到 body 里
- document.body.appendChild(toastDom.$el);
- queue.push(toastDom);
- singleToast=true;
- return toastDom;
- }
- };
- // 注册为全局组件的函数
- function toast(options= {}) {
- const toastDom = createInstance();
- toastDom.message =typeof options === 'string' ? options : options.message;
- toastDom.type = options.type || 'success';
- toastDom.duration = options.duration || 3000;
- toastDom.position = options.position || 'middle';
- if(!toastDom.message){
- toastDom.showToast =singleToast= false;
- }else{
- toastDom.showToast=true;
- setTimeout(() => {toastDom.showToast =singleToast= false} ,toastDom.duration);
- }
- }
- // 将组件注册到 vue 的 原型链里去,
- // 这样就可以在所有 vue 的实例里面使用 this.$toast()
- // Vue.prototype.$toast = showToast
- Vue.prototype.$toast = toast;
- export default toast
设置 singleToast 和 queue 的目的在于: 确保同一时期界面上只有一个 toast, 不能同时出现多个 toast.
由于 toast 会初始化, 因此为了避免在任何操作之前界面上就出现一个 toast, 用 if 语句判断:
如果没有传入的 message, 则不显示 toast(这样可以使得初始化的 toast 不显示)
否则显示, 并且过一定时间消失, 只有 singleToast 为 false, 说明此刻界面上没有 toast, 才能再新建一个 toast 实例(因为此时 if 判断内 queue.length 不为 0[初始化的 toast 组件本身占了一个位置] , 而 singleToast 为 false, 因此可以创建)
第三步: 使用
在 main.js 添加如下代码:
- import toast from './components/toast/index'
- Vue.use(toast)
创建需要调用的 Vue 文件:
- <template>
- <div>
- <input type="button" value="显示弹窗" @click="showToast">
- </div>
- </template>
- <script>
- export default {
- methods: {
- showToast () {
- this.$toast({message:'加载中',type:'loading',position:'bottom',
- duration:'2000'});
- // this.$toast('成功提示');
- }
- }
- }
- </script>
可以看到一共两种方式, 可以以对象方式传入参数, 也可以只传入字符串, 其他采用默认设置.
总结
以上所述是小编给大家介绍的 SVue 自定义 toast 组件的实例代码, 希望对大家有所帮助, 如果大家有任何疑问请给我留言, 小编会及时回复大家的. 在此也非常感谢大家对脚本之家网站的支持!
来源: http://www.jb51.net/article/145686.htm