Vue自定义全局Toast和Loading

框架

浏览数:400

2019-4-19

如果我们的Vue项目中没有用到任何UI框架的话,为了更好的用户体验,肯定会用到loading和toast。那么我们就自定义这两个组件吧。

1、Toast组件

首先,在common下新建global文件夹,存放我们的toast.vue和toast.js两个文件(当然文件的具体位置你可以自行安排)。

(1). toast.vue

<template lang="html">
  <div v-if="isShowToast" class="toast-container" @touchmove.prevent>
    <!-- 这里content为双花括号 -->
    <span class="loading-txt">{content}</span>
  </div>
</template>

<script>
export default {
  data () {
    return {
      isShowToast: true,
      content: ''
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.toast-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(255, 255, 255, 0.1);
}
.toast-msg {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 60%;
  padding: 35px;
  border-radius: 10px;
  font-size: 28px;
  line-height: 36px;
  background: #eee;
  color: #666;
}
</style>

(2). toast.js

import Vue from 'Vue'
import ToastComponent from './Toast.vue'

const Toast = {}
let showToast = false // 存储loading显示状态
let toastNode = null // 存储loading节点元素
const ToastConstructor = Vue.extend(ToastComponent)

Toast.install = function (Vue, options) {
  // 参数
  var opt = {
    duration: '1200'
  }
  for (var property in options) {
    opt[property] = options[property]
  }
  Vue.prototype.$toast = function (tips, type) {
    if (type === 'hide') {
      toastNode.isShowToast = showToast = false
    } else {
      if (showToast) {
        // 如果toast还在,则不再执行
        return
      }
      toastNode = new ToastConstructor({
        data: {
          isShowToast: showToast,
          content: tips
        }
      })
      toastNode.$mount() // 挂在实例,为了获取下面的toastNode.$el
      document.body.appendChild(toastNode.$el)
      toastNode.isShowToast = showToast = true
      setTimeout(function () {
        toastNode.isShowToast = showToast = false
      }, opt.duration)
    }
  };

  ['show', 'hide'].forEach(function (type) {
    Vue.prototype.$toast[type] = function (tips) {
      return Vue.prototype.$toast(tips, type)
    }
  })
}

export default Toast

然后,我们需要把写好的组件在/src/main.js中引用一下。

import Toast from './components/common/global/toast'

Vue.use(Toast)

最后,怎么使用呢?只需在要用的地方this.$toast.show(‘hello world’)

2、Loading组件

loading组件只需要照着toast组件搬过来,稍微改下就可以了。

首先,在common下新建global文件夹,存放我们的loading.vue和loading.js两个文件。

(1). loading.vue

<template lang="html">
  <div v-if="isShowLoading" class="loading-container">
    <div class="loading-box">
      <img class="loading-img" :src="require('../../../assets/images/loading.png')">
      <!-- 这里content为双花括号 -->
      <span class="loading-txt">{content}</span>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      isShowLoading: false,
      content: ''
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.loading-container {
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0);
  z-index: 1000;
}
.loading-box {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 150px;
  height: 150px;
  border-radius: 10px;
  background: #e5e5e5;
}
.loading-img {
  width: 70px;
  height: 70px;
  animation: rotating 2s linear infinite;
}
@keyframes rotating {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(1turn);
  }
}
.loading-txt {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 24px;
  color: #666;
}
</style>

(2). loading.js

import Vue from 'Vue'
import LoadingComponent from './Loading.vue'

const Loading = {}
let showLoading = false // 存储loading显示状态
let loadingNode = null // 存储loading节点元素
const LoadingConstructor = Vue.extend(LoadingComponent)

Loading.install = function (Vue) {
  Vue.prototype.$loading = function (tips, type) {
    if (type === 'hide') {
      loadingNode.isShowLoading = showLoading = false
    } else {
      if (showLoading) {
        // 如果loading还在,则不再执行
        return
      }
      loadingNode = new LoadingConstructor({
        data: {
          isShowLoading: showLoading,
          content: tips
        }
      })
      loadingNode.$mount() // 挂在实例,为了获取下面的loadingNode.$el
      document.body.appendChild(loadingNode.$el)
      loadingNode.isShowLoading = showLoading = true
    }
  };

  ['show', 'hide'].forEach(function (type) {
    Vue.prototype.$loading[type] = function (tips) {
      return Vue.prototype.$loading(tips, type)
    }
  })
}

export default Loading

然后,在/src/main.js中引用一下loading组件。

import Loading from './components/common/global/loading'

Vue.use(Loading)

最后,只需在要用的地方this.$loading.show(‘hello world’)、 this.$loading.hide()