创建和使用 Toast 组件

使用 fixed 定位, 弹出 1.5 秒后自动隐藏,并添加淡入淡出过渡效果

  1. <template>
  2. <transition name="fade">
  3. <div class="toast" v-if="showToast">{{message}}</div>
  4. </transition>
  5. </template>
  6. <script lang="ts">
  7. export default {
  8. props: ['message', 'showToast']
  9. }
  10. </script>
  11. <style lang="scss" scoped>
  12. .toast {
  13. padding: 16px;
  14. border-radius: 5px;
  15. background: rgba(0, 0, 0, 0.35);
  16. color: white;
  17. font-size: 16px;
  18. position: fixed;
  19. left: 50%;
  20. top: 50%;
  21. transform: translate(-50%, -50%);
  22. z-index: 5;
  23. }
  24. .fade-enter-from,
  25. .fade-leave-to {
  26. opacity: 0;
  27. }
  28. .fade-enter-active,
  29. .fade-leave-active {
  30. transition: opacity 750ms ease;
  31. }
  32. </style>

使用

  1. <template>
  2. // ...
  3. <Toast :showToast="data.showToast" :message="data.message"/>
  4. </template>
  5. <script>
  6. import Toast from '@/components/Toast.vue'
  7. export default {
  8. components: {
  9. Toast
  10. },
  11. setup(){
  12. const data = reactive(
  13. {
  14. message: '',
  15. showToast: false
  16. }
  17. )
  18. const showToast = (message: string) => {
  19. data.showToast = true
  20. data.message = message
  21. setTimeout(() => {
  22. data.showToast = false
  23. data.message = ''
  24. }, 1500)
  25. }
  26. const handleLogin = async () => {
  27. try {
  28. // ...
  29. if(result.data.verifySuccess === true) {
  30. // ...
  31. } else {
  32. showToast('用户名或密码错误')
  33. }
  34. } catch(e) {
  35. showToast('请求失败')
  36. }
  37. }
  38. return {
  39. data,
  40. handleLogin,
  41. }
  42. }
  43. }
  44. </script>

封装逻辑代码

目前Toast组件的逻辑代码分散在其他组件中,应整合到一起,以便重复使用
封装成 useToastEffect 放在 Toast 组件中并 export

  1. <template>
  2. <transition name="fade">
  3. <div class="toast" v-if="showToast">{{message}}</div>
  4. </transition>
  5. </template>
  6. <script lang="ts">
  7. import { reactive } from "vue"
  8. export default {
  9. props: ['message', 'showToast']
  10. }
  11. export const useToastEffect = () => {
  12. const toastData = reactive(
  13. {
  14. message: '',
  15. showToast: false
  16. }
  17. )
  18. const showToast = (message: string) => {
  19. toastData.showToast = true
  20. toastData.message = message
  21. setTimeout(() => {
  22. toastData.showToast = false
  23. toastData.message = ''
  24. }, 2000)
  25. }
  26. return {
  27. toastData,
  28. showToast
  29. }
  30. }
  31. </script>

其他组件要使用直接 import 即可, 很像 react 的hooks

  1. <template>
  2. <div class="login">
  3. // ...
  4. <Toast :showToast="toastData.showToast" :message="toastData.message"/>
  5. </div>
  6. </template>
  7. <script lang="ts">
  8. import Toast, {useToastEffect} from '@/components/Toast.vue'
  9. export default {
  10. components: {
  11. Toast
  12. },
  13. setup(){
  14. // ...
  15. const {toastData, showToast} = useToastEffect()
  16. const handleLogin = async () => {
  17. try {
  18. // ...
  19. if(result.data.verifySuccess === true) {
  20. // ...
  21. } else {
  22. showToast('用户名或密码错误')
  23. }
  24. } catch(e) {
  25. showToast('请求失败')
  26. }
  27. }
  28. return {
  29. data,
  30. handleLogin,
  31. toastData
  32. }
  33. }
  34. }
  35. </script>