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

2019-09-02 23:19:18 +08:00
 Hopetree

但愿这个图能显示

情况如图所示,这个计算属性会在 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>

8062 次点击
所在节点    Vue.js
42 条回复
murmur
2019-09-02 23:24:26 +08:00
promise 是异步请求啊,你这个问题不懂的话建议先搞一下 promise 是个什么东西
既然是异步 ajax 那返回也应该是一个 promise 才对
murmur
2019-09-02 23:26:39 +08:00
老老实实用 method 绑事件不好么 看你是搜索提示 这个建议直接用定时器检测改动 你不知道中文输入法有什么坑
然后 a 做成 data 里的变量 检测到有文字输入就搜 搜了在 then 里赋值给 a suggestion 那里就是 a 了
xxx749
2019-09-02 23:28:37 +08:00
亲亲,这边建议您用 Watch 呢,您这边另起一个属性把 GET 拿到的数据赋值给这个属性就行了呢
krisfive
2019-09-02 23:28:54 +08:00
emmm 楼上 +1
hahasong
2019-09-02 23:30:19 +08:00
计算属性里套 ajax,令人窒息的操作。ajax 还没结束。空的 a 就被返回了
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
2019-09-02 23:33:47 +08:00
建议先学习 js 异步的概念…

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

@hahasong 因为我是在学 vue,想着尽量用更多的插件来实现功能,都是为了探索
CDL
2019-09-02 23:38:41 +08:00
computed 只会监听 data,prop 这类属性值
Allianzcortex
2019-09-02 23:38:45 +08:00
@Allianzcortex 最后还要再 return a,其实是[因为要用到返回的结果]所以能保证[等到 axios 请求结果出来后再返回 computed 的结果]
Hopetree
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
2019-09-03 00:00:57 +08:00
@ochatokori 我理解的流程也是这样的,那么这个 fix 方法理论上应该可以?
karnaugh
2019-09-03 00:10:17 +08:00
天秀。。。。
lqzhgood
2019-09-03 00:16:08 +08:00
用 watch 要 debounce
不然你就是 ddos
Allianzcortex
2019-09-03 00:32:37 +08:00
@ochatokori 算了,看了下,除了 await 外确实没有别的方法,就算是用变量也不行
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
2019-09-03 09:01:23 +08:00
sctext 变动频繁吗?如果变动频繁记得加防抖..
Zink99
2019-09-03 09:02:09 +08:00
同步任务执行完成后才执行 .then() 中的代码,所以 a 是空

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

你 return a 的时候,a = json_str 还没有执行呢
no1xsyzy
2019-09-03 09:17:24 +08:00
@SilentDepth 阻塞式请求也是可以同步的,但也会冻结页面,不过 CPU 消耗比较少

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/597355

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX