• 【Vue3从零开始-实战】S10:Toast弹窗组件开发


    前言

    实战已经开始了!前面几篇文章已经将登录注册和模拟接口请求的内容讲完了,但是在登录失败或者接口请求失败的时候,还缺少一个提示内容,虽然浏览器也给我们提供了alert之类的提示框,但是作为前端开发,不仅为了美观,更加为了以后可以复用,所以我们可以写一个组件专门用来做提示弹窗信息的。

    补充

    在上一章节中,可能在调用接口的时候,URL写错了或者接口API写错了,都会导致错误信息,但是当我们用async/await去请求接口的时候,会发现并不会执行下面的else语句的。

    👉 比如我们把baseURL中的fastmock写错成fastmock111

    export const post = (url, data = {}) => {
      return new Promise((resolve, reject) => {
        axios.post(url, data, {
          baseURL: 'https://www.fastmock111.site/mock/eb925863ecc46f2108cd43d75f96c1cd/pro'
        }).then((response) => {
          resolve(response)
        }, err => {
          reject(err)
        })
      })
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    👉 然后我们再去请求post的时候,就会发现并不会提示登录失败

    const handleLogin = async () => {
      const result = await post('/api/user/login', {
        mobile: data.mobile,
        password: data.password
      })
      if (result.data.code === 0) {
        localStorage.isLogin = true
        router.push({ name: 'Home' })
      } else {
        console.log('登录失败')
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ahJMxbLN-1658392764352)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/23ae703e9dca4373bca1eaf705bee115~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?)]

    点击登录之后,浏览器控制台就会直接报错了。对于async/await这种写法要怎么去控制接口请求报错呢?可以用js里面的try/catch方法。

    const handleLogin = async () => {
      try {
        const result = await post('/api/user/login', {
          mobile: data.mobile,
          password: data.password
        })
        if (result.data.code === 0) {
          localStorage.isLogin = true
          router.push({ name: 'Home' })
        } else {
          console.log('登录失败')
        }
      } catch (e) {
        console.log('请求失败')
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JnQHok65-1658392764353)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5a261a6a32e040d49115642245789bc4~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?)]

    虽然控制台还是有接口报错,但是同样也将提示信息告诉我们了,这样也就方便我们定位问题所在了。

    Toast组件

    🌀 在开发组件之前,我们需要去新建一个vue文件,但是这种公共的组件就不能直接新建在views目录下面了,还记得最初创建项目时,有一个components文件夹嘛?这里面就是用来存放公共组件的地方。

    👉 在cpmponents文件夹下面新建一个Toast.vue

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XrkMVuka-1658392764354)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e7c90a8141ca49838a67abfefa9e1f40~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?)]

    👉 Toast组件中的DOM结构和样式也比较简单

    
    
    
    
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    👉 Login.vue中引入Toast组件

    import Toast from '../../components/Toast' 
    
    • 1
    components: {
        Toast
    }, 
    
    • 1
    • 2
    • 3
     
    
    • 1

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pXbf6vJ1-1658392764354)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/47a645fc9b054dabaeb54251956502b3~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?)]

    🔆 可以看到页面上就会直接显示出Toast了。

    组件显隐

    目前来看Toast组件是一直保持显示状态的,我们需要在点击登录之后才显示出来才行,并且间隔 2 秒之后自动隐藏。

    👉 在setup函数中的data里面定义一个showToast,用于判断组件显示隐藏

    const data = reactive({
      showToast: false,
    }) 
    
    • 1
    • 2
    • 3

    👉 在Toast组件标签上通过v-if指令来判断showToast,为true的时候就显示,反之隐藏

     
    
    • 1

    👉 需要在handleLogin函数中请求接口失败时,将showToast设为true 👉 将showToast设为true的同时,需要用setTimeout方法将showToast在间隔 2 秒之后设为false

    const handleLogin = async () => {
      try {
        const result = await post('/api/user/login', {
          mobile: data.mobile,
          password: data.password
        })
        if (result.data.code === 0) {
          localStorage.isLogin = true
          router.push({ name: 'Home' })
        } else {
          data.showToast = true
          console.log('登录失败')
          setTimeout(() => {
            data.showToast = false
          }, 2000)
        }
      } catch (e) {
        data.showToast = true
        console.log('请求失败')
        setTimeout(() => {
            data.showToast = false
        }, 2000)
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G5V0EZm4-1658392764354)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/47190ffd6f84428b96d65d5fce28618d~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?)]

    组件传参

    在调用登录接口时,我们判断了登录失败和请求失败的逻辑,但是这些提示不应该直接用comsole.log输出到控制台,应该将提示语动态传递给Toast组件显示出来。

    👉 在setup函数中的data里面定义toastMessage

    const data = reactive({
        showToast: false,
        toastMessage: ''
    }) 
    
    • 1
    • 2
    • 3
    • 4

    👉 在Toast组件标签中使用toastMessage

     
    
    • 1

    👉 Toast组件中通过props接收传递过来的message

    export default {
      props: ['message']
    } 
    
    • 1
    • 2
    • 3

    👉 将handleLogin方法中的console.log换成toastMessage

    data.toastMessage = '请求失败' 
    
    • 1

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a8qI8JU1-1658392764354)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3f9f45a309a54a2f9101cd8976253a48~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?)]

    拆分组件

    按照上面的代码来写的话,基本上是把所有的逻辑全部放在了一个setup函数里面,如果以后还要增加新的组件,那么这一个页面的代码量就又会很难维护了。而且也不符合compositionAPI中将逻辑归纳在一块区域的原则,所以我们需要拆分组件中的逻辑,也就是逻辑必须是跟随组件在一起的。

    👉 打开Toast组件,将关于Toast组件逻辑全部放到一个新的方法中,然后通过export导出,可以让外部引入

    export const useToastEffect = () => {
    
      const toastData = reactive({
        showToast: false,
        toastMessage: ''
      })
    
      const showToast = (message) => {
        toastData.showToast = true
        toastData.toastMessage = message
        setTimeout(() => {
          toastData.showToast = false
          toastData.toastMessage = ''
        }, 2000)
      }
      
      return { toastData, showToast }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 逻辑部分和setup函数中写法一致,都是需要将绑定的数据定义在reactive中,最后通过return返回给外部。

    👉 Login页面中不仅要引入Toast组件,还需要引入Toast的逻辑方法

    import Toast, { useToastEffect } from '../../components/Toast' 
    
    • 1

    👉 setup函数中就可以直接使用Toast组件中的逻辑方法useToastEffect

    setup () {
        const router = useRouter()
        const data = reactive({ username: '', password: '' })
        const { toastData, showToast } = useToastEffect()
    
        const handleLogin = async () => {
          try {
            const result = await post('/api/user/login', {
              username: data.username,
              password: data.password
            })
            if (result.data.code === 0) {
              localStorage.isLogin = true
              router.push({ name: 'Home' })
            } else {
              showToast('登陆失败')
            }
          } catch (e) {
            showToast('请求失败')
          }
        }
    
        const handleRegisterClick = () => {
          router.push({ name: 'Register' })
        }
    
        return { handleLogin, handleRegisterClick, data, toastData }
      } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    总结

    本篇文章主要是将Toast组件进行封装,并把setup函数中关于Toast组件的部分全部拆分出来放到组件里面进行统一管理。

  • 相关阅读:
    昨天面试一个武大的,10年经验,薪资只要1万二!
    Linux常见命令总结
    KL散度
    WinRT: 可能是 Windows 上最好用的 Native ABI 和远程调用方案
    【C++】智能指针
    机器学习笔记:初始化0的问题
    1.3媒介视角的语言观
    JUC第四讲:Java中的锁/CAS原理与案例分析
    华为OD DNA序列(100分)【java】A卷+B卷
    【畅购商城】详情页详情之商品详情
  • 原文地址:https://blog.csdn.net/web2022050902/article/details/125915668