V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
elboble
V2EX  ›  Vue.js

还是 Vue loading 过场的疑问?

  •  
  •   elboble · 2023-03-17 11:49:34 +08:00 · 2645 次点击
    这是一个创建于 617 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原来登录界面没有等待的过场傻等,后来学习大家的都有个 Loading 或者 Checking 的过场,就用 v-if 加了。登录请求后台返回后就取消 loading ,成功了就跳转业务页面,失败就重新登录,逻辑上很简单没啥问题。

    但是跑起来发现个问题,跳转的业务页面需要资源比较多,第一次加载要个 1-2 秒,这时候会即使成功了先跳出登录界面 1-2 秒,再被业务页面覆盖,这就有点尴尬。

    我现在的办法是如果登录成功,就不改 loading 了,一直转到业务页面加载出来。登录失败才改 loading 。 这个是不是不太优雅。

    没进过厂,想请教这个小问题是怎么处理的?

    <template>
      <div>
        <div v-if="isLoading">
          <LoadingSpinner />
        </div>
        <div v-else>
        //登录页面
        ....
        </div>
      </div>
      ...
    </template>
    
    <script lang="ts">
    ....
    const setup(){
        const btnClick = () => {
          if (username.value && password.value) {
            authStore.returnUrl = route.query.redirect;
            isLoading.value = true;
            authStore
              .login(username.value, password.value)
              .then((ret) => {
                if (ret !== 0) {
                  message.warning("账号或密码错误。");
                  **isLoading.value = false; //现在在这里**
                } else {
                  message.success("登录成功");
                  router.push((route.query.redirect as LocationQueryValue) || "/");
                }
              })
              .catch((err) => {
                console.error(err);
              })
              .finally(() => {
                **// isLoading.value = false; //原来在这里**
              });
          } else {
            message.warning("请输入用户名和密码。");
          }
        };
    }
    ....
    </script>
    
    16 条回复    2023-03-18 12:17:58 +08:00
    op351
        1
    op351  
       2023-03-17 11:53:50 +08:00
    ```
    这时候会即使成功了先跳出登录界面 1-2 秒,再被业务页面覆盖,这就有点尴尬。
    ```
    这句话什么意思?
    molvqingtai
        2
    molvqingtai  
       2023-03-17 11:57:23 +08:00
    同问
    hervey0424
        3
    hervey0424  
       2023-03-17 12:00:52 +08:00   ❤️ 1
    登录按钮上就 loading, 登录失败了取消, 成功了直接跳转到业务页面
    Huelse
        4
    Huelse  
       2023-03-17 12:04:06 +08:00
    两种方案:
    1 、Loading 为顶层覆盖
    2 、Loading 放在 v-else ,需要显示的内容为 v-if="data && !loading"
    elboble
        5
    elboble  
    OP
       2023-03-17 12:05:47 +08:00
    @op351 我也不太清楚,我是这样分析的,开始 isLoading.value = false 是在 finally 里,这样后端登录校验返回后,无论正确错误,isLoading 都会 false 。如果正确,应该 router.push 到业务界面了,但是因为业务界面加载时间长,或者其他原因比较慢,会进 v-else ,就是又出现了登录界面。

    所以后来我把 isLoading.value = false 只放到登录失败的情况里,如果正确自然就不会进 v-else 了。

    对了,这是个单页面应用。
    molvqingtai
        6
    molvqingtai  
       2023-03-17 12:11:50 +08:00
    从代码可以看出登录交互有问题,登录页面 loading 时也应该一直存在,loading 可以弹个 toast loading 或者 button loading ,未避免接口响应太快,导致 loading 动画闪一下有个巧妙的解决办法:

    const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

    await Promise.allSettled([sleep(1000), login()]);
    // loading 结束跳转到首页
    op351
        7
    op351  
       2023-03-17 12:24:04 +08:00   ❤️ 1
    @elboble
    所以你的问题是 使用 router.push 跳转到下一个页面的过程中 如何处理上一个页面仍然残留的问题
    参考这个链接吧
    https://router.vuejs.org/zh/guide/advanced/navigation-failures.html
    3282361
        8
    3282361  
       2023-03-17 14:30:50 +08:00
    这好像应该用 <Suspense>
    subframe75361
        9
    subframe75361  
       2023-03-17 17:55:48 +08:00
    用异步组件?
    djkloop
        10
    djkloop  
       2023-03-17 18:32:54 +08:00
    弄个 store... 在下个页面干掉...你这情况让我想起了 vben 那个后台...登录成功了但是 其实下个页面的资源还在加载...一般页面路由是懒加载...要不然笨办法把首页不要懒加载
    lscho
        11
    lscho  
       2023-03-17 18:42:28 +08:00
    楼上正解,你的 loading 其实是两个页面的状态,第一个是登录页面的请求等待状态,第二个是登录成功跳转目标页面资源加载、数据初始化的状态。你的做法只解决了第一个登录页面的请求等待状态,但是第二个页面的初始化状态没有解决。

    所以把 loading 提出来放到全局 store 中,点击登录按钮时开始 loading ,直到第二个页面加载完再结束 loading
    billly
        12
    billly  
       2023-03-17 19:00:10 +08:00
    业务页面再加个 loading
    cyrbuzz
        13
    cyrbuzz  
       2023-03-17 19:05:19 +08:00
    感觉你这个直接把 v-if="isLoading"扩展成 v-if="isLoading || isLogin"就完事了。

    分析下来你的 loading 仅处理了是不是完成了登录 API 的调用,完全没什么问题,逻辑紧密也很容易理解。

    理想情况下 loading 完之后应该立即跳转到下一个页面,不应该在当前页面停留,但因为某些原因导致仍然会在此页面停留一段时间,就导致了问题。

    顺着这条路解决思路就是:
    1. 在继续停留的这段时间内仍然保持 loading 状态(做法如前所说,loading 的判断变成是否处在 API 调用中或者是否已经登录,或者楼上说的在下个页面处理(= =不太推荐,这样逻辑太撕裂了))。
    2. 专门做一下路由切换的过渡动画,这个 Vue 开箱即用,https://router.vuejs.org/zh/guide/advanced/transitions.html
    3. 预(懒)加载一些资源(楼上说的异步组件),让将要去的页面尽快显示出来。

    如果是我的话= =,通用性强的方法就是 2+3 一起做,实际上也应该是项目中应该做到的事情(ToC),省事就 1 咯。
    WilliamLin
        14
    WilliamLin  
       2023-03-18 10:10:39 +08:00 via iPhone
    @lscho 同感
    elboble
        15
    elboble  
    OP
       2023-03-18 11:32:55 +08:00
    @lscho @cyrbuzz @molvqingtai @op351 @djkloop @Huelse @hervey0424 感谢各位。
    现在没用单独的 loading 界面,直接用带 loading 的按钮,这样登录界面不消失,就需要在 isloading 中 disable input 和 button 了,界面没闪,问题没那么明显。

    关键问题是业务页面加载慢的问题,按道理应该是业务页面加载也要有 loading 过场。
    不过暂时就用登录正确就不切换 isloading 状态了,直接等业务页面加载出来,最简单。

    transition 还在学习中。

    这么个基本的交互,前端都有这么多坑,按道理要求应该很高,不至于像 V 上说的这么卷吧。
    LykorisR
        16
    LykorisR  
       2023-03-18 12:17:58 +08:00
    可以嵌套一层,loading 在父组件,然后 login 和业务的子组件更新父组件的状态
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2786 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 12:51 · PVG 20:51 · LAX 04:51 · JFK 07:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.