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

估计是老问题了, vue 在组件中 created 里用 ajax 或者 axios 请求数据,但是数据在 mounted 前没返回

  •  
  •   elboble · 2021-11-08 16:46:10 +08:00 · 2471 次点击
    这是一个创建于 1102 天前的主题,其中的信息可能已经有所发展或是发生改变。
    render 页面控制台上会出错,怎么处理?

    改成 async: false ,不太优雅。看别人页面上转圈圈,直到数据返回,这个怎么实现的。
    24 条回复    2021-12-07 16:15:19 +08:00
    liuidetmks
        1
    liuidetmks  
       2021-11-08 17:01:13 +08:00
    不是应该加一个 loading 状态吗
    silk
        2
    silk  
       2021-11-08 17:03:50 +08:00
    ???????????????????
    多看书 多思考
    M003
        3
    M003  
       2021-11-08 17:05:47 +08:00   ❤️ 1
    兄弟,你想法错了。
    我是封装 axios 中请求前,将该请求丢到一个数组当中。然后开启 loading (开启前判断 loading 是否已经开启)
    请求结束后,把该请求从数组中删除(删除后判断数组内是否有别的,如果没有就关闭 loading )

    这样可以保证只有一个 loading 在开启。
    JKeita
        4
    JKeita  
       2021-11-08 17:08:55 +08:00
    添加拦截器?
    shintendo
        5
    shintendo  
       2021-11-08 17:12:22 +08:00
    <div v-if="loading">转圈圈</div>
    <div v-else>渲染数据</div>

    data: {
    loading: true,
    数据: null
    },
    created () {
    发请求().then(返回 => {
    this.数据 = 返回
    this.loading = false
    })
    }
    elboble
        6
    elboble  
    OP
       2021-11-08 17:21:23 +08:00
    @shintendo 这个方法可以,但是如果这样的话,每个要读数据的页面几乎都要被 v-if ,v-else 包装下,vue 是不是可以给再包装下,给我们省点事,不知道有没有装饰器。

    不过实话实说,虽然数据比 mount 来的晚,但是在页面上看不出,只是控制台上会提示渲染时某个变量 undefined ,可能网络只慢了一点点,数据回来后,马上重新渲染了,人感觉不出。
    learnshare
        7
    learnshare  
       2021-11-08 17:21:25 +08:00   ❤️ 1
    关注数据(状态),而非其他任何东西

    你的问题核心是渲染时访问了不存在的数据,这里出了错。

    有两个解法:
    1. 渲染备用内容,如上面介绍的 loading 组件。发起请求前设置 loading = true ;请求结束后设置 loading = false 。根据 loading 决定渲染什么。
    2. 模板里检查数据是否可用。user && user.id
    learnshare
        8
    learnshare  
       2021-11-08 17:24:46 +08:00
    @elboble 不要假设请求能够瞬间完成
    B 站某个 JS 加载了几十秒,页面完全死掉

    v-if 有什么错,模板里有逻辑就是很繁琐
    peterczg
        9
    peterczg  
       2021-11-08 17:39:24 +08:00
    楼主认为这是一个「问题」,意思是 Vue.js 框架本身有问题吗?是觉得 Vue.js 的每个 Hook 都设计成 async 模式吗?在生命周期函数里面进行异步操作,要等异步操作完成才能执行下一个钩子吗?

    如果你想这么做,也不是不行,把 Vue.js 源码拷一份过来,把里面所有的 Hook 都改成 async 调用。然后书写的业务代码如下
    ```js
    export default {
    async created(){
    await axios('')
    },
    mounted(){
    },
    }
    ```

    如果你没有理清同步与异步的关系,那暂且认定你是个写 Vue.js 的新手,因为不管是在 Vue.js created 钩子和 React 已经废弃的 componentWillMount 钩子里面,都是同步调用。
    elboble
        10
    elboble  
    OP
       2021-11-08 17:39:39 +08:00
    @learnshare 自己学艺不精啊,都只教到在 created 和 mounted 里发 ajax 获数据,但是没教怎么处理异步函数返回是不确定的,v-if 加起来。
    elboble
        11
    elboble  
    OP
       2021-11-08 17:46:53 +08:00
    @learnshare 是的,昨天第一次 webpack 打包,发现加了 elmentUI ,第一个页面有 4M 多,一个 js 3M ,这 4G 网络差一点都够呛,深切体会到移动互联网在 4G 上才能爆发。

    后话,删了 elmentUI 先用 bootstrap 吧
    elboble
        12
    elboble  
    OP
       2021-11-08 17:50:38 +08:00
    @peterczg 思维定式比较严重了,但是异步函数处理起来的确很头疼。写过一个 H5 页面里,几个消息要传递,还有回调,都是异步的,套了好几层。

    异步函数有点像管杀不管埋,反正活干完了,后面怎么配合你自己想办法吧
    M003
        13
    M003  
       2021-11-08 17:54:40 +08:00
    @elboble 可以尝试把 elementUI 提出去,采用 CDN 方式 不打包进去。
    simple233
        14
    simple233  
       2021-11-08 17:57:28 +08:00
    如果是用 elementUI ,建议看看 loading 组件,并且自带 v-loading 指令。。
    如果不是,自己写一个自定义指令(谷歌搜一下都有),用法:<div v-loading="loading" > </div>
    loading 为布尔值,true 为 loading 状态,false 显示原本页面。
    douxc
        15
    douxc  
       2021-11-08 18:07:19 +08:00
    1 、在 mounted 里发请求
    2 、楼上任意一个回复都能实现
    christin
        16
    christin  
       2021-11-08 19:57:47 +08:00 via iPhone
    @M003 防抖不就是用在这里的嘛 你的方法有些繁琐
    darknoll
        17
    darknoll  
       2021-11-08 20:13:23 +08:00
    这是异步的问题,你直接用 v-if 判断就行了
    M003
        18
    M003  
       2021-11-09 09:47:52 +08:00
    @christin 可以提出来,这样我也学习学习,那个方法也是在视频中学习到的。
    dfkjgklfdjg
        19
    dfkjgklfdjg  
       2021-11-09 09:53:07 +08:00
    呃....除了吐槽你《 mounted 前没返回》异步数据这个,
    之外想和你说不喜欢 loading 的,你也可以试试看骨架屏.....
    christin
        20
    christin  
       2021-11-09 09:58:20 +08:00 via iPhone
    @M003 可以百度搜索 loading 闪烁 有很多使用防抖的例子 我就不嫌丑了
    gadfly3173
        21
    gadfly3173  
       2021-11-09 10:29:57 +08:00
    额。。。异步数据既然你能写成模板,说明你知道里面有哪些字段,你不想写 v-if 那就给 data 设个默认值呗。。。转圈圈就用 element 的 v-loading 或者找别的 loading 的解决方案就好了
    elboble
        22
    elboble  
    OP
       2021-11-09 11:36:03 +08:00
    @gadfly3173 嗯嗯,是的,已经加了 v-if 处理了,只是觉得异步,回调这些方法难得控制。
    gadfly3173
        23
    gadfly3173  
       2021-11-09 12:38:17 +08:00
    @elboble #22 这些逻辑当然是要你自己处理的,异步回调也是前端开发的基础内容了。现在有 async await 语法糖,写起来已经很轻松了
    KouShuiYu
        24
    KouShuiYu  
       2021-12-07 16:15:19 +08:00
    我是这样写的

    v-loading="isLoading"

    然后
    this.isLoading = true;
    // 异步请求
    this.isLoading = false;
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3060 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 14:15 · PVG 22:15 · LAX 06:15 · JFK 09:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.