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

兄弟们, vue 网页有没有办法实现页面首页加载超过 1 秒才显示 loading, 1 秒内就不显示 loading 吗

  •  
  •   dafuyang · 2022-12-13 23:11:03 +08:00 · 5497 次点击
    这是一个创建于 721 天前的主题,其中的信息可能已经有所发展或是发生改变。
    目前我采用的是常规的实现方式,在还 vue 没渲染的时候显示 loading ,挂载渲染后隐藏 loading ,首次效果不错,但是后续浏览器有缓存了,在加载很快的情况下,loading 的显示就会闪一下,感觉不是很爽,有办法实现我标题中的这种需求吗。。
    52 条回复    2023-01-14 00:05:49 +08:00
    lambdaq
        1
    lambdaq  
       2022-12-13 23:15:30 +08:00
    强行假装 1 秒再展示即可。
    dafuyang
        2
    dafuyang  
    OP
       2022-12-13 23:17:48 +08:00
    @lambdaq 这个我也想到了,延迟 1 秒在隐藏,看看其他兄弟有没有好办法,不行的话只能这么改咯。。
    renmu
        3
    renmu  
       2022-12-13 23:25:41 +08:00 via Android
    全屏 loading 的话可以强行多看几秒 loading
    rabbbit
        4
    rabbbit  
       2022-12-13 23:28:14 +08:00
    const timeoutId = setTimeout(() => this.loading = true, 1000)
    try {
    const res = await getResource()
    } catch(err) {
    console.log(err)
    }
    this.loading = false
    clearTimeout(timeoutId)
    horseInBlack
        5
    horseInBlack  
       2022-12-13 23:28:58 +08:00
    骨架屏 / v-cloak
    vace
        6
    vace  
       2022-12-13 23:29:43 +08:00
    如果你的 loading 在实例中的话,可以用 defineAsyncComponent 定义一个入口的异步组件,在 loader 里面加载数据和其他组件,用 delay 控制 loadingComponent 的展示时机。
    SQLException
        7
    SQLException  
       2022-12-13 23:30:34 +08:00
    记一下平均耗时?超过一定范围才渲染 loading
    anguiao
        8
    anguiao  
       2022-12-13 23:31:25 +08:00
    强行显示 1 秒的 loading 呗,不然还有啥办法呢?毕竟你不能预知要加载多久啊😂
    dafuyang
        9
    dafuyang  
    OP
       2022-12-13 23:41:54 +08:00
    @SQLException 咋判断时间呢,我题目就是问这个的意思。。
    SQLException
        10
    SQLException  
       2022-12-13 23:43:47 +08:00
    @dafuyang #9 https://juejin.cn/post/6844903569900978189
    参考这个?不是让你算现在这个页面加载多久再决定是否开启 loading
    是让你算前面几个页面的平均值,小于一定值就禁用 loading
    darkengine
        11
    darkengine  
       2022-12-14 00:04:33 +08:00
    在 index.html 的 head 元素里用 js script 脚本设置个 1 秒的 timeout ,到了再显示 loading 。当在 vue 加载出来时判断这个 timeout 在不,如果在的话(加载时间小于 1 秒)取消掉。
    sheeta
        12
    sheeta  
       2022-12-14 00:05:24 +08:00   ❤️ 8
    刚好 1.1 秒加载完成呢,loading 不还是一闪而过吗,所以问题不在这
    lightyisu
        13
    lightyisu  
       2022-12-14 00:53:25 +08:00
    以前好像做过但是没用判断不出来 contentloaded 时间 伪 1S 感觉在浪费时间尽管人感受不出来速度。所以感觉没必要折腾完美。
    yfugibr
        14
    yfugibr  
       2022-12-14 01:16:38 +08:00 via Android   ❤️ 1
    300ms 内没加载完才显示 loading ,如果显示 loading ,至少显示 1s
    MrHyde
        15
    MrHyde  
       2022-12-14 04:17:26 +08:00
    1s 已经够久的了
    huijiewei
        16
    huijiewei  
       2022-12-14 08:08:57 +08:00
    我是强制显示 1 秒的 loading 。。
    gaolingyi
        17
    gaolingyi  
       2022-12-14 08:15:57 +08:00   ❤️ 1
    antd 的 Spin 就是这种设计, 但是我觉得, 直接展示 loading,至少展示 300ms 的逻辑更简单
    ragnaroks
        18
    ragnaroks  
       2022-12-14 08:32:55 +08:00   ❤️ 1
    直接显示加载指示器,给这个组件加上 1 秒的 opacity 从 0 到 100% 的 transtion
    cangcang
        19
    cangcang  
       2022-12-14 09:25:44 +08:00
    让你的 loading 延迟一秒展示
    SmiteChow
        20
    SmiteChow  
       2022-12-14 09:29:06 +08:00
    谁喜欢看 loading 啊,一闪而过代表网速性能好,是正反馈啊。
    makelove
        21
    makelove  
       2022-12-14 09:49:05 +08:00
    我就是这么用的,实现没用 js ,用的是 css animation 就有的延迟动画 1s 功能
    yamedie
        22
    yamedie  
       2022-12-14 09:59:23 +08:00 via Android
    我会选择用 Promise.race ,好处是省得手动 set 和 clear 定时器(也不用去比对 Date.now()),逻辑也更清晰一点儿。

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

    let isLoading = false;

    const promiseSleep = sleep(1000);

    const promiseAjax = fetch(xxx).then(res => {xxxx 业务逻辑; return true}).finally(() => {isLoading = false});

    Promise.race([promiseSleep, promiseAjax]).then(res => {if (!res) isLoading = true});
    yamedie
        23
    yamedie  
       2022-12-14 10:03:34 +08:00 via Android
    噢,没注意审题,想在 vue 运行时还没加载时就开始计时并显示 loading ,应该在 html 的 head 里尽早加载独立的 script 来控制骨架屏的显隐吧
    justdoit123
        24
    justdoit123  
       2022-12-14 10:10:56 +08:00
    强制至少 loading X 秒的体验会好一点,效果稳定。比如,至少 loading 0.3 秒,如果 0.3 秒后页面还没准备好,那就继续 loading 。
    darknoll
        25
    darknoll  
       2022-12-14 10:15:24 +08:00
    vue 没渲染的时候显示 loading ,是怎么整的?
    kealm
        26
    kealm  
       2022-12-14 10:27:59 +08:00   ❤️ 1
    这个叫 grace time 。一般的处理方式是:1. 增加一个延迟 2. 增加最短展示时间。
    延迟时间内不显示 loading ,如果延迟时间内加载完毕,直接进入。如果延迟时间内没有加载完毕,显示 loading ,时间是 MIN(最短展示时间,实际时间)。
    kealm
        27
    kealm  
       2022-12-14 10:28:24 +08:00
    @kealm MIN => MAX
    dreamn
        28
    dreamn  
       2022-12-14 10:33:22 +08:00
    试试渐变显示 loading ,渐变退出 loading 的方案呢?
    这样视觉上就是不是闪烁效果了.....
    rrZ2C
        29
    rrZ2C  
       2022-12-14 10:41:18 +08:00
    设置至少 loading 1 秒
    flyingghost
        30
    flyingghost  
       2022-12-14 12:20:13 +08:00
    进页展示一个透明 1s 后渐入 100%的动画 loading 。
    4771314
        31
    4771314  
       2022-12-14 15:32:05 +08:00
    这个确定不是 yy 的需求或者老板的需求?
    听起来不怎么靠谱
    YouTing
        32
    YouTing  
       2022-12-14 15:46:52 +08:00
    请求速度快的时候出现 loading ,而较快时不出现。月经问题了,淘宝在用 setTimeout ,缺点是一秒左右的 loading 体验不好,0.9 秒没有 loading ,1.1 秒 loading 一闪而过
    likunyan
        33
    likunyan  
       2022-12-14 15:51:46 +08:00
    都被你们玩花了,该显示就显示,不显示就不要显示。
    jorneyr
        34
    jorneyr  
       2022-12-14 16:21:10 +08:00
    underscore 的 throttle 函数可以处理这个问题。
    296727
        35
    296727  
       2022-12-14 16:22:50 +08:00
    。。。。一个 css 的 transiton 不就可以了,还要这么折腾
    sanmaozhao
        36
    sanmaozhao  
       2022-12-14 16:31:44 +08:00
    这题我做过。
    分析一下题目:
    >> 在还 vue 没渲染的时候显示 loading ,挂载渲染后隐藏 loading
    这一条,把 loading 界面放到 vue 实例挂在的 DOM 元素里面就行了,挂载后组件渲染出来的 DOM 会替换原本的内容

    >> 首页加载超过 1 秒才显示 loading ,1 秒内就不显示 loading
    给上一条的 loading 界面加个 css 样式,透明度为 0 ,所以开始时看不到这个 loading 界面
    然后再加个 css animation ,1s 后把透明度变为 1 ,所以这时就能看到了
    样例代码:
    @keyframes fadeIntLoading {
    from {
    opacity: 0;
    }
    to {
    opacity: 1;
    }
    }

    animation: fadeIntLoading 0.1s linear 1s forwards;
    opacity: 0;
    sanmaozhao
        37
    sanmaozhao  
       2022-12-14 16:33:29 +08:00
    fadeIntLoading 不小心多打了个 t ,不过不影响功能
    loolac
        38
    loolac  
       2022-12-14 16:36:47 +08:00
    loading 添加渐显过渡动画,超过 1s 才全部显示出来,小于 1s 就是没全部显示就渐隐了
    jeffwcx
        39
    jeffwcx  
       2022-12-14 16:39:24 +08:00
    这个一般放到 html 里面做,不放在 vue 里面做
    sanmaozhao
        40
    sanmaozhao  
       2022-12-14 16:53:42 +08:00
    写了个样例,直接就有效果

    https://codepen.io/sanmao/pen/eYKwLRv
    isbase
        41
    isbase  
       2022-12-14 16:59:17 +08:00
    这个看起来和你说的异曲同工,https://baiyun.me/improve-the-user-experience-for-react-apps
    bitkuang8
        42
    bitkuang8  
       2022-12-14 18:10:50 +08:00
    这样行的不...

    ```js
    // 初始 loading 为 false

    let timer = setTimeout(() => {
    loading = true
    }, 1000)

    // 在 App.vue 的 mounted 钩子中
    loading = false // 假设加载资源已经超过 1s ,在挂载完成时取消 loading

    clearInterval(loading) // 假设 1s 内已经挂载完成,取消 loading
    ```
    leonPuck
        43
    leonPuck  
       2022-12-14 18:10:52 +08:00
    如果用了 RxJS , 也可以实现,https://juejin.cn/post/7176943529057321017
    raolight
        44
    raolight  
       2022-12-14 18:20:09 +08:00
    不就普通的延时 Loading 么?

    都是差不多的思路,一般是设置延迟 2~3 秒显示 Loading ,如果期间数据还没加载完,那就继续显示 Loading ;

    如果 2~3 秒内已经加载完了,就取消 Loading
    dssxzuxc
        45
    dssxzuxc  
       2022-12-14 19:26:40 +08:00
    js 文件本身的加载时间是未知的,所以任何 js 层面的处理都达不到你想要的效果。如果这个误差你能接受,那随便挑一个方法都行。
    grewer
        46
    grewer  
       2022-12-14 19:32:04 +08:00
    关键词: setTimeout
    Actrace
        47
    Actrace  
       2022-12-14 19:43:24 +08:00
    试试用 tmpUI 做真加载进度
    https://github.com/tmplink/tmpUI
    thulof
        48
    thulof  
       2022-12-14 19:47:40 +08:00
    特意登陆来回复你一下:
    把 Loading 写在 HTML 模版中,页面开始加载时 setTimeout 计时一秒开始展示 Loading DOM
    在 Vue 的初始化逻辑中加载完成时 remove 掉 Loading DOM 即可
    gengliangcais
        49
    gengliangcais  
       2022-12-15 11:39:00 +08:00
    /** 秒级响应不再显示 loading 弹窗 */
    const delay = 1000
    let timeoutId = setTimeout(() => {
    if (loading) {
    timeoutId = 0;
    //
    showLoading()
    }
    }, delay);

    // 响应里面
    if(timeoutId==0){
    closeLoading()
    }
    dafuyang
        50
    dafuyang  
    OP
       2022-12-21 21:14:04 +08:00
    @darkengine
    @yfugibr
    @ragnaroks
    @kealm
    @dreamn
    @flyingghost
    @rrZ2C
    @YouTing
    @296727
    @sanmaozhao
    @sanmaozhao
    @raolight
    @grewer
    @thulof
    兄弟们,感谢大家的意见!!!这段时间梯子挂了,上不来。。综合试了一下,js settimeout 或者是动画延迟执行在加上渐变过渡都可以满足俺的需求,再次谢谢各位!!
    lynan
        51
    lynan  
       2022-12-27 18:46:44 +08:00
    @darknoll 把 loading 写在 #app 里,vue 初始化以后会替换 #app 的节点内容
    humbass
        52
    humbass  
       2023-01-14 00:05:49 +08:00
    本质上应该有 4 个状态:

    0 - 未知状态 - 按楼主的意思相当于是白屏,或者显示骨架页内容
    1 - 有缓存数据,准备加载数据
    2 - 没有缓存,显示 loading
    3 - 数据已装载

    1 和 3 合并也可以

    不关 setTimeout 什么事,如果要用到 延时,说明只写了两个状态
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1433 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 180ms · UTC 17:30 · PVG 01:30 · LAX 09:30 · JFK 12:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.