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

vue 如何实现 loading 读条,加载完成后显示页面?

  •  
  •   LeeReamond · 2021-04-18 22:38:44 +08:00 · 6005 次点击
    这是一个创建于 1098 天前的主题,其中的信息可能已经有所发展或是发生改变。

    以前都是做单个组件的 axios 回调绑定加载完成事件,感觉还比较简单,现在想做一个全局读条,不会做了

    具体分为两个问题,其一是如何让用户在第一次打开页面时读一个条。比如用户第一次访问我的网站,而我的前端 spa 体积比较大,可能读个一两秒钟,这段时间我要在 vue 还没加载完成之前放一个 loading,然后等 vue 加载完成之后删掉这个 loading,没想好怎么做。

    其二是 vue 加载完成之后,单个路由页面的 loading,比如用户默认打开 index.html 之后,这时候 vue 的 js 已经在本地了,现在想跳转到 catalogue 页面,这个页面需要再额外加载若干图片和 css/js 脚本,我希望资源全部加载完成之前不要展示页面,这种应该怎么做呢?

    32 条回复    2021-04-20 00:41:23 +08:00
    lvdb
        1
    lvdb  
       2021-04-18 22:42:56 +08:00 via Android
    useEffect
    joesonw
        2
    joesonw  
       2021-04-18 23:29:08 +08:00 via iPhone
    纯 html 放 loadong,加载完后再干掉。
    freak118
        4
    freak118  
       2021-04-18 23:57:18 +08:00
    @lvdb 能详细说说吗
    ch2
        5
    ch2  
       2021-04-19 00:18:20 +08:00 via iPhone
    在首屏的那个 html 里做 loading,等 js 啥的加载完了再让它消失
    LeeReamond
        6
    LeeReamond  
    OP
       2021-04-19 01:29:05 +08:00
    @ch2
    @joesonw
    思路是这么个思路,但是具体操作怎么做呢,是类似让 vue 搜索 loading 的 id 然后干掉这个 element 么。

    另外一个问题是 vue 怎么知道自己加载完成了,因为我用 vuetify 模板,还需要引入一些 google 字体和图标 css 之类的,可能还有图片
    LeeReamond
        7
    LeeReamond  
    OP
       2021-04-19 01:56:46 +08:00
    @LeeReamond 试了一下往 index.html 里加东西。。结果变成不管哪个路由都会先闪过一下 loading 画面,感觉不太好
    kmore
        8
    kmore  
       2021-04-19 08:07:38 +08:00 via iPhone
    vue 生命周期函数 beforeCreate 实例初始化加入 loading,created 实例创建完成结束 loading,全局写个 mixin
    yesC
        9
    yesC  
       2021-04-19 08:55:18 +08:00
    如果用到 vue-router 的话可以看看路由守卫,可以配合组件 nprogress,这个效果和你说的需求很相似,可以参照着改改。
    WEBUG
        10
    WEBUG  
       2021-04-19 08:56:49 +08:00
    @LeeReamond 初次加载的 loading 写在 index.html 里面,写一个内部 css,在 index 最下方写 js 方法干掉 css 。其他阶段的 loading 就写在 vue 里面了。
    plk403
        11
    plk403  
       2021-04-19 09:00:46 +08:00
    我也有一个问题,怎样让当前路由的图片全部加载完之前显示 loading 呢? ? ? 就是判断图片全部加载完毕再显示页面...给跪了
    lh900519
        12
    lh900519  
       2021-04-19 09:05:48 +08:00 via Android
    @LeeReamond 把 loading 的代码放到#app 元素里面,vue 开始渲染的时候,会把#app 里面的元素给替换掉
    iplayio2019
        13
    iplayio2019  
       2021-04-19 09:16:04 +08:00 via Android
    我以前这么写过,写一个 loading 全局计数器,开始请求计数器加 1,请求完成计数器减 1,百分比增加百分 20,如果百分比小于 80%,直到计数器为 0 。
    cyrbuzz
        14
    cyrbuzz  
       2021-04-19 09:46:05 +08:00
    还有一个思路是用 SSR,Nuxt 里写 layout,这样就可以完全使用 Vue 的生命周期。
    cereschen
        15
    cereschen  
       2021-04-19 10:38:24 +08:00
    都没说到点子上去 用异步组件 请阅读文档
    emeab
        16
    emeab  
       2021-04-19 11:08:26 +08:00   ❤️ 1
    v-cloak?
    pouta
        17
    pouta  
       2021-04-19 11:13:35 +08:00
    看官方文档,全局路由守卫
    chouchoui
        18
    chouchoui  
       2021-04-19 11:15:19 +08:00
    zhuweiyou
        19
    zhuweiyou  
       2021-04-19 11:40:45 +08:00
    直接在 public/index.html 里面写 loading show
    cereschen
        20
    cereschen  
       2021-04-19 12:08:49 +08:00   ❤️ 1
    我觉得直接说去看文档 确实有些不够负责任
    我这里给出了示例代码 组件的加载完全由自己掌握

    export default new Router({
    routes: [
    {
    path: '/',
    name: 'start-page',
    component: () => ({
    // 需要加载的组件 (应该是一个 `Promise` 对象)
    component: new Promise(r => {
    setTimeout(() => {
    r(import('@/views/start'))
    }, 2000);
    }),
    // 异步组件加载时使用的组件
    loading: {
    render(h) {
    h('div', 'loading.....')
    }
    },
    // 加载失败时使用的组件
    error: {
    render(h) {
    h('div', 'error.....')
    }
    },
    // 展示加载时组件的延时时间。默认值是 200 (毫秒)
    delay: 5000,
    // 如果提供了超时时间且组件加载也超时了,
    // 则使用加载失败时使用的组件。默认值是:`Infinity`
    timeout: 30000
    })
    }]
    })
    hm20062006ok
        21
    hm20062006ok  
       2021-04-19 13:48:06 +08:00   ❤️ 1
    第一个问题, 如果“用户第一次访问我的网站”打开的是首页。下面有一个效果:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="renderer" content="webkit">

    <title>WebSiteName</title>
    <style type="text/css">body {
    margin: 0;
    padding: 0
    }

    .loading {
    width: 100%;
    height: 100%;
    background: #fff;
    position: absolute
    }

    .lodingco {
    width: 200px;
    height: 80px;
    text-align: center;
    z-index: 1;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto
    }

    .loading h2 {
    color: #666;
    margin: 0;
    text-transform: uppercase;
    letter-spacing: .1em;
    font-size: 20px;
    font-weight: 400;
    font-family: cursive
    }

    .loading span {
    display: inline-block;
    vertical-align: middle;
    width: .6em;
    height: .6em;
    margin: .19em;
    background: #007DB6;
    border-radius: .6em;
    -webkit-animation: loading 1s infinite alternate;
    animation: loading 1s infinite alternate;
    animation: loading 1s infinite alternate
    }

    .loading span:nth-of-type(2) {
    background: #008FB2;
    -webkit-animation-delay: .2s;
    animation-delay: .2s
    }

    .loading span:nth-of-type(3) {
    background: #009B9E;
    -webkit-animation-delay: .4s;
    animation-delay: .4s
    }

    .loading span:nth-of-type(4) {
    background: #00A77D;
    -webkit-animation-delay: .6s;
    animation-delay: .6s
    }

    .loading span:nth-of-type(5) {
    background: #00B247;
    -webkit-animation-delay: .8s;
    animation-delay: .8s
    }

    .loading span:nth-of-type(6) {
    background: #5AB027;
    -webkit-animation-delay: 1s;
    animation-delay: 1s
    }

    .loading span:nth-of-type(7) {
    background: #A0B61E;
    -webkit-animation-delay: 1.2s;;
    animation-delay: 1.2s
    }

    @-webkit-keyframes loading {
    0% {
    opactty: 0
    }
    100% {
    opacity: 1
    }
    }

    @keyframes loading {
    0% {
    opacity: 0
    }
    100% {
    opacity: 1;
    }
    }</style>
    </head>
    <body>

    <div id="app">
    <div class="loading">
    <div class="lodingco"><h2>WebSiteName Loading</h2>
    <span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
    </div>
    </div>

    </body>


    </script>
    </html>
    joesonw
        22
    joesonw  
       2021-04-19 13:56:08 +08:00
    @LeeReamond js 加载完后, 加载 img 的时候加一个 onload, 手动计数.
    rozbo
        23
    rozbo  
       2021-04-19 14:16:19 +08:00
    slert
        24
    slert  
       2021-04-19 14:58:57 +08:00
    nuxt 的 spa 模式就自带这个效果
    ToPoGE
        25
    ToPoGE  
       2021-04-19 16:55:09 +08:00
    在 index.html 的里写加载样式,
    在 index.html 里写 window.onload 事件,取消加载样式
    你在 vue 里写的加载,只能用于 vue.js 载入完成后才生效,不然之前就是白屏
    其实说白了就是 index.html 加载完成,但是你 vue 及相关库没载入完成,之间的 loading 效果
    LeeReamond
        26
    LeeReamond  
    OP
       2021-04-19 18:56:14 +08:00
    @ToPoGE 感觉可以操作,大佬请教一下 onload 怎么理解,它这个加载完成,是指 vue 将 dom 渲染完,还是说文件下载到本地( vue 还没执行 create 之前)就已经触发 onload 了?如果 vue 中又添加了新的依赖,应该怎么理解呢,比如下载了 vue 的文件,然后 vue 又要求某个 css,onload 会触发两次么
    HiCode
        27
    HiCode  
       2021-04-19 20:19:48 +08:00
    这两个问题凑一起真是绝了!

    https://v2ex.com/t/771311#reply23

    楼主先把最基础的 html 和 js 学好了,这个问题就不是问题了。
    LeeReamond
        28
    LeeReamond  
    OP
       2021-04-19 21:19:55 +08:00
    @HiCode 无非讨论一些实现上的惯例,我觉得跟学没学好基础没什么关系,而且本来前端也比较随意。看你的回复是觉得太简单了不屑于讨论这类问题?
    HiCode
        29
    HiCode  
       2021-04-19 23:49:05 +08:00
    @LeeReamond 真有趣,等你基础补好了,你回头再看看你上面给其他人的回复,就知道我为什么会说是基础的问题。

    这不是屑不屑的问题,而是说答案就在那里,有些人直接往答案的方向走,有些人选择 v2 上提问,前者事半功倍,后者事倍功半。

    没有说哪种对哪种错,时间是自己的,开心就好!
    LeeReamond
        30
    LeeReamond  
    OP
       2021-04-20 00:06:45 +08:00
    @rozbo 大佬,你这个方案我试了一下,在本地 dev 调试的话,每次刷新任何界面都会闪过 loading 界面,build 之后上传到远端以后反而不会了,大佬能讲下啥原因么
    LeeReamond
        31
    LeeReamond  
    OP
       2021-04-20 00:10:06 +08:00
    @HiCode 确实挺有趣的,可能不是技术的问题,应该只是单纯的阅读理解问题。至于你说的上面其他人的回复,楼上提的 nprogress,路由守卫自定义,和 vue 接管前插入几个方案我都试了,没有找到特别完美的解决方案,我倒不是很懂你说的补好基础再回来看指看什么。
    HiCode
        32
    HiCode  
       2021-04-20 00:41:23 +08:00
    第 5 楼:“思路是这么个思路,但是具体操作怎么做呢,是类似让 vue 搜索 loading 的 id 然后干掉这个 element 么。”

    直接通过 dom 接口查找 loading 响应的节点,删掉,跟 vue 没关系,找个基本的 HTML DOM 教程看一下,最基本的就行。这个都可以说没有思路,感觉就不是做前端的了。

    第 21 楼:“感觉可以操作,大佬请教一下 onload 怎么理解,它这个加载完成,是指 vue 将 dom 渲染完,还是说文件下载到本地( vue 还没执行 create 之前)就已经触发 onload 了?如果 vue 中又添加了新的依赖,应该怎么理解呢,比如下载了 vue 的文件,然后 vue 又要求某个 css,onload 会触发两次么”

    他说的是“ window.onload ”,window 对象的 onload 事件,看 dom 教程吧……


    看 dom 教程吧……
    看 dom 教程吧……
    看 dom 教程吧……
    看 dom 教程吧……
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2776 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 14:50 · PVG 22:50 · LAX 07:50 · JFK 10:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.