vue 的 computed 相关的一个问题,求助 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Hopetree
V2EX    Vue.js

vue 的 computed 相关的一个问题,求助

  •  
  •   Hopetree
    Hopetree 2019-09-02 23:19:18 +08:00 8519 次点击
    这是一个创建于 2229 天前的主题,其中的信息可能已经有所发展或是发生改变。

    但愿这个图能显示

    情况如图所示,这个计算属性会在 sctext 变动时触发,实际上也的确会这样,但是我在 HTML 中使用{{ suggestion }}发现是空的,但是 console 日志会刷新值,所以很奇怪,为甚返回不到值?

    如果图挂了,看源码:

    <template> <div> ... 方便查看所以省略其他 <p>{{ suggestion }}</p> </div> </template> <script> export default { data() { return { // 从 store 里面读取数据并使用 sctype: "", scdata: {}, sctypelist: [], sctext: "", }; }, created() { // 设置默认值 var default_type = this.$store.getters.searchTypes[0]; this.sctype = default_type; this.sctypelist = this.$store.getters.searchTypes; this.scdata = this.$store.state.searchList[default_type]; }, computed: { suggestion: function() { var a = '' this.$axios .get("/baidu/su", { params: { wd: this.sctext } }) .then(ret => { var json_str = ret.data.match(/s:(\[.*\])}\);/); if (json_str) { var json_str = json_str[1]; } console.log(json_str); a = json_str }); return a } }, methods: { // 选择表单变化的时候同步数据 changedata: function(command) { this.sctype = command; this.scdata = this.$store.state.searchList[command]; } } }; </script> <style scoped> img { width: 1.2rem; margin: 0rem 0.2rem -0.2rem 0rem; } </style> 
    42 条回复    2019-09-03 17:05:36 +08:00
    murmur
        1
    murmur  
       2019-09-02 23:24:26 +08:00
    promise 是异步请求啊,你这个问题不懂的话建议先搞一下 promise 是个什么东西
    既然是异步 ajax 那返回也应该是一个 promise 才对
    murmur
        2
    murmur  
       2019-09-02 23:26:39 +08:00
    老老实实用 method 绑事件不好么 看你是搜索提示 这个建议直接用定时器检测改动 你不知道中文输入法有什么坑
    然后 a 做成 data 里的变量 检测到有文字输入就搜 搜了在 then 里赋值给 a suggestion 那里就是 a 了
    xxx749
        3
    xxx749  
       2019-09-02 23:28:37 +08:00 via Android
    亲亲,这边建议您用 Watch 呢,您这边另起一个属性把 GET 拿到的数据赋值给这个属性就行了呢
    krisfive
        4
    krisfive  
       2019-09-02 23:28:54 +08:00
    emmm 楼上 +1
    hahasong
        5
    hahasong  
       2019-09-02 23:30:19 +08:00
    计算属性里套 ajax,令人窒息的操作。ajax 还没结束。空的 a 就被返回了
    Allianzcortex
        6
    Allianzcortex  
       2019-09-02 23:33:32 +08:00
    像是 async 和 await 的问题,因为 axios 返回的数据没有被用到,所以会 先 return 再 console.log(). 这里提一个 fix 的方法,把 return a 放到 resolvoe 函数里,楼主可以试下:

    var a = ' '

    a = this.$axios.get(...).then(... return json_str)
    ochatokori
        7
    ochatokori  
       2019-09-02 23:33:47 +08:00 via Android   1
    建议先学习 js 异步的概念…

    这样说吧,你这个代码的执行顺序是
    var a='' //赋值,没问题
    axios //哦?这个是异步的,先发请求,结果丢一边等我有空再说
    return a//a 还空着,就被 computed 出去了
    //刚才有个异步还没处理,现在轮到你了
    //得到结果,给 a 赋值,这个时候 a 当然有值,但是 computed 方法早就跑完了
    //这里的流程实际上有问题,为了方便理解我省去了微任务和宏任务那些东西… promise 是微任务(面试要考)
    Hopetree
        8
    Hopetree  
    OP
       2019-09-02 23:37:38 +08:00
    @murmur
    @xxx749
    我现在是这样,的确能拿到返回值了,但是由于增加了一个属性,所以每次改动输入,都会重复调用 2 次接口,我还是看看你推荐的 watch 吧

    @hahasong 因为我是在学 vue,想着尽量用更多的插件来实现功能,都是为了探索
    CDL
        9
    CDL  
       2019-09-02 23:38:41 +08:00
    computed 只会监听 data,prop 这类属性值
    Allianzcortex
        10
    Allianzcortex  
       2019-09-02 23:38:45 +08:00
    @Allianzcortex 最后还要再 return a,其实是[因为要用到返回的结果]所以能保证[等到 axios 请求结果出来后再返回 computed 的结果]
    Hopetree
        11
    Hopetree  
    OP
       2019-09-02 23:55:05 +08:00
    @xxx749 非常感谢,我刚看了一下 watch,发现这个才是我需要的方法,已经实现了效果,下面是我改的

    ```
    watch: {
    sctext(val) {
    this.$axios
    .get("/baidu/su", { params: { wd: this.sctext } })
    .then(ret => {
    var json_str = ret.data.match(/s:(\[.*\])}\);/);
    if (json_str) {
    var json_str = json_str[1];
    }
    console.log(json_str);
    this.suggestion = json_str
    });
    }
    },
    ```
    Allianzcortex
        12
    Allianzcortex  
       2019-09-03 00:00:57 +08:00
    @ochatokori 我理解的流程也是这样的,那么这个 fix 方法理论上应该可以?
    karnaugh
        13
    karnaugh  
       2019-09-03 00:10:17 +08:00
    天秀。。。。
    lqzhgood
        14
    lqzhgood  
       2019-09-03 00:16:08 +08:00 via Android
    用 watch 要 debounce
    不然你就是 ddos
    Allianzcortex
        15
    Allianzcortex  
       2019-09-03 00:32:37 +08:00
    @ochatokori 算了,看了下,除了 await 外确实没有别的方法,就算是用变量也不行
    SilentDepth
        16
    SilentDepth  
       2019-09-03 08:31:44 +08:00
    @Allianzcortex #15 如果你是说要让这个过程「同步地」完成,强制循环等待法可解。只是,考虑到 JS 整体是单线程的,你的页面会被冻结(

    其实 computed 应对这种需求也不是没有用,只是直观上没那么方便。创建两个普通状态,loading 和 data,然后触发异步动作,首先 loading = true,异步返回后 loading = false 并把返回数据赋值给 data。计算属性同时访问这俩普通状态,当 loading === true 时返回占位内容,loading === false 时返回 data。因为 loading 的变化也会导致计算属性刷新,所以可以直接被模板使用。

    这些过程直接写到组件里会比较乱,所以用 Vue.obserable( ) 或 @vue/composition-api 是更好的做法。(是的我就是来安利 Vue 3 的~)
    VancleefL
        17
    VancleefL  
       2019-09-03 09:01:23 +08:00
    sctext 变动频繁吗?如果变动频繁记得加防抖..
    Zink99
        18
    Zink99  
       2019-09-03 09:02:09 +08:00
    同步任务执行完成后才执行 .then() 中的代码,所以 a 是空

    了解下异步?
    https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/7
    meepo3927
        19
    meepo3927  
       2019-09-03 09:17:23 +08:00
    Ajax 异步 ,

    你 return a 的时候,a = json_str 还没有执行呢
    no1xsyzy
        20
    no1xsyzy  
       2019-09-03 09:17:24 +08:00
    @SilentDepth 阻塞式请求也是可以同步的,但也会冻结页面,不过 CPU 消耗比较少
    tumobi
        21
    tumobi  
       2019-09-03 09:21:39 +08:00
    还是使用 async await 吧
    no1xsyzy
        22
    no1xsyzy  
       2019-09-03 09:25:44 +08:00
    基础概念问题…… 附一个 2014 年的演讲:
    SilentDepth
        23
    SilentDepth  
       2019-09-03 09:27:49 +08:00
    @no1xsyzy #20 那个开关不是都被废弃了吗,没准哪天都不能用了(
    hyy1995
        24
    hyy1995  
       2019-09-03 09:34:24 +08:00
    你这个问题其实跟 vue 没啥关系,纯粹就是网络请求没请求完成前,你就 return 返回了,此时数据都还没取到,这就是个异步问题,太秀了吧。。。
    liuguang
        25
    liuguang  
       2019-09-03 09:38:04 +08:00
    因为这个是异步的,请求还没完成,就 return 了
    dfourc
        26
    dfourc  
       2019-09-03 09:45:40 +08:00
    计算属性嵌套异步请求,龟龟,骚操作
    jrtzxh020
        27
    jrtzxh020  
       2019-09-03 09:48:27 +08:00 via iPhone
    有个 asyncComputed 的库 可以了解一下
    lscho
        28
    lscho  
       2019-09-03 09:48:56 +08:00
    亲亲,建议您学习一下 js 噢
    mikoshu
        29
    mikoshu  
       2019-09-03 10:08:10 +08:00
    只想说一句 666 好歹把 return 写到 promise 里面呀
    Curtion
        30
    Curtion  
       2019-09-03 10:12:08 +08:00
    这是异步问题啊,和我初学 js 时犯的问题的一样,建议看看书巩固下基础
    mikoshu
        31
    mikoshu  
       2019-09-03 10:15:58 +08:00
    @mikoshu 就算 return 写到 promise 里 还得 return axios 然后返回一个 promise 估计也不好使 果然只能用 await 了 还有楼主改成 watch 的话 如果这个值变动很快 比如监听 input 的 input 事件 就得故意加延迟查询 不然请求太多
    Biwood
        32
    Biwood  
       2019-09-03 10:17:05 +08:00 via Android
    1 楼和 7 楼都已经说到点子上了,去了解一下 Javascript 同步和异步的原理和机制,比乱猜乱尝试有意义多了。后面还一堆扯到 async await 的,到底是有多菜啊各位,学习框架就真的不用学底层和基础知识了吗
    tolking
        33
    tolking  
       2019-09-03 10:19:20 +08:00
    建议你打开项目的 eslint 或者配置下。这种情况就会直接提示
    ```
    Unexpected asynchronous action in "suggestion" computed property.eslint(vue/no-async-in-computed-properties)
    ```
    shintendo
        34
    shintendo  
       2019-09-03 10:36:55 +08:00
    上面说用 await 可以解决的各位,麻烦上个代码好吗?
    shintendo
        35
    shintendo  
       2019-09-03 10:37:12 +08:00
    @Biwood +1 我都惊了
    ljpCN
        36
    ljpCN  
       2019-09-03 10:55:05 +08:00 via Android
    楼主已经解决了,而且也很耐心地去寻求解决方案并尝试。不过还是想说,学 vue 之前,先学 js
    shakaraka
        37
    shakaraka  
    PRO
       2019-09-03 11:06:26 +08:00
    这边建议 lz 先重新学习 vue 呢亲,async 也要另外学一下
    Sapp
        38
    Sapp  
       2019-09-03 12:48:17 +08:00
    我好久没用过 computed 了,但是我似乎记得,这个属性推荐的是做同步操作啊?你这个需求应该在坚挺某个输入的值变化,然后再调用请求,请求完成之后设置 this.a
    mamahaha
        39
    mamahaha  
       2019-09-03 13:02:06 +08:00
    你这个相当于是暗恋一个人,对方却不知道。
    johnnyNg
        40
    johnnyNg  
       2019-09-03 13:49:59 +08:00
    建议重学 js
    mikoshu
        41
    mikoshu  
       2019-09-03 17:02:58 +08:00
    @Biwood
    @shintendo
    emmm 确实是 估计大家一开始都没想那么多 以为直接给 suggestion 加 async 然后在 promise 的位置 await 一下 再 return 就好了 (包括我也是,已经是习惯把 await 当成是同步了,是有点想当然了)因为毕竟是语法糖 这样会导致 computed 根本无法使用
    supuwoerc
        42
    supuwoerc  
       2019-09-03 17:05:36 +08:00
    终于见到我会的问题了(滑稽)
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1157 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 23:30 PVG 07:30 LAX 16:30 JFK 19:30
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86