但愿这个图能显示
情况如图所示,这个计算属性会在 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>
![]() | 1 murmur 2019-09-02 23:24:26 +08:00 promise 是异步请求啊,你这个问题不懂的话建议先搞一下 promise 是个什么东西 既然是异步 ajax 那返回也应该是一个 promise 才对 |
![]() | 2 murmur 2019-09-02 23:26:39 +08:00 老老实实用 method 绑事件不好么 看你是搜索提示 这个建议直接用定时器检测改动 你不知道中文输入法有什么坑 然后 a 做成 data 里的变量 检测到有文字输入就搜 搜了在 then 里赋值给 a suggestion 那里就是 a 了 |
![]() | 3 xxx749 2019-09-02 23:28:37 +08:00 via Android 亲亲,这边建议您用 Watch 呢,您这边另起一个属性把 GET 拿到的数据赋值给这个属性就行了呢 |
4 krisfive 2019-09-02 23:28:54 +08:00 emmm 楼上 +1 |
![]() | 5 hahasong 2019-09-02 23:30:19 +08:00 计算属性里套 ajax,令人窒息的操作。ajax 还没结束。空的 a 就被返回了 |
![]() | 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) |
7 ochatokori 2019-09-02 23:33:47 +08:00 via Android ![]() 建议先学习 js 异步的概念… 这样说吧,你这个代码的执行顺序是 var a='' //赋值,没问题 axios //哦?这个是异步的,先发请求,结果丢一边等我有空再说 return a//a 还空着,就被 computed 出去了 //刚才有个异步还没处理,现在轮到你了 //得到结果,给 a 赋值,这个时候 a 当然有值,但是 computed 方法早就跑完了 //这里的流程实际上有问题,为了方便理解我省去了微任务和宏任务那些东西… promise 是微任务(面试要考) |
![]() | 8 Hopetree OP |
9 CDL 2019-09-02 23:38:41 +08:00 computed 只会监听 data,prop 这类属性值 |
![]() | 10 Allianzcortex 2019-09-02 23:38:45 +08:00 @Allianzcortex 最后还要再 return a,其实是[因为要用到返回的结果]所以能保证[等到 axios 请求结果出来后再返回 computed 的结果] |
![]() | 11 Hopetree OP @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 }); } }, ``` |
![]() | 12 Allianzcortex 2019-09-03 00:00:57 +08:00 @ochatokori 我理解的流程也是这样的,那么这个 fix 方法理论上应该可以? |
13 karnaugh 2019-09-03 00:10:17 +08:00 天秀。。。。 |
![]() | 14 lqzhgood 2019-09-03 00:16:08 +08:00 via Android 用 watch 要 debounce 不然你就是 ddos |
![]() | 15 Allianzcortex 2019-09-03 00:32:37 +08:00 @ochatokori 算了,看了下,除了 await 外确实没有别的方法,就算是用变量也不行 |
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 的~) |
![]() | 17 VancleefL 2019-09-03 09:01:23 +08:00 sctext 变动频繁吗?如果变动频繁记得加防抖.. |
![]() | 18 Zink99 2019-09-03 09:02:09 +08:00 同步任务执行完成后才执行 .then() 中的代码,所以 a 是空 了解下异步? https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/7 |
![]() | 19 meepo3927 2019-09-03 09:17:23 +08:00 Ajax 异步 , 你 return a 的时候,a = json_str 还没有执行呢 |
![]() | 20 no1xsyzy 2019-09-03 09:17:24 +08:00 @SilentDepth 阻塞式请求也是可以同步的,但也会冻结页面,不过 CPU 消耗比较少 |
![]() | 21 tumobi 2019-09-03 09:21:39 +08:00 还是使用 async await 吧 |
![]() | 22 no1xsyzy 2019-09-03 09:25:44 +08:00 基础概念问题…… 附一个 2014 年的演讲: |
23 SilentDepth 2019-09-03 09:27:49 +08:00 @no1xsyzy #20 那个开关不是都被废弃了吗,没准哪天都不能用了( |
![]() | 24 hyy1995 2019-09-03 09:34:24 +08:00 你这个问题其实跟 vue 没啥关系,纯粹就是网络请求没请求完成前,你就 return 返回了,此时数据都还没取到,这就是个异步问题,太秀了吧。。。 |
25 liuguang 2019-09-03 09:38:04 +08:00 因为这个是异步的,请求还没完成,就 return 了 |
![]() | 26 dfourc 2019-09-03 09:45:40 +08:00 计算属性嵌套异步请求,龟龟,骚操作 |
![]() | 27 jrtzxh020 2019-09-03 09:48:27 +08:00 via iPhone 有个 asyncComputed 的库 可以了解一下 |
28 lscho 2019-09-03 09:48:56 +08:00 亲亲,建议您学习一下 js 噢 |
![]() | 29 mikoshu 2019-09-03 10:08:10 +08:00 只想说一句 666 好歹把 return 写到 promise 里面呀 |
![]() | 30 Curtion 2019-09-03 10:12:08 +08:00 这是异步问题啊,和我初学 js 时犯的问题的一样,建议看看书巩固下基础 |
![]() | 31 mikoshu 2019-09-03 10:15:58 +08:00 @mikoshu 就算 return 写到 promise 里 还得 return axios 然后返回一个 promise 估计也不好使 果然只能用 await 了 还有楼主改成 watch 的话 如果这个值变动很快 比如监听 input 的 input 事件 就得故意加延迟查询 不然请求太多 |
![]() | 32 Biwood 2019-09-03 10:17:05 +08:00 via Android 1 楼和 7 楼都已经说到点子上了,去了解一下 Javascript 同步和异步的原理和机制,比乱猜乱尝试有意义多了。后面还一堆扯到 async await 的,到底是有多菜啊各位,学习框架就真的不用学底层和基础知识了吗 |
![]() | 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) ``` |
![]() | 34 shintendo 2019-09-03 10:36:55 +08:00 上面说用 await 可以解决的各位,麻烦上个代码好吗? |
36 ljpCN 2019-09-03 10:55:05 +08:00 via Android 楼主已经解决了,而且也很耐心地去寻求解决方案并尝试。不过还是想说,学 vue 之前,先学 js |
![]() | 37 shakaraka PRO 这边建议 lz 先重新学习 vue 呢亲,async 也要另外学一下 |
![]() | 38 Sapp 2019-09-03 12:48:17 +08:00 我好久没用过 computed 了,但是我似乎记得,这个属性推荐的是做同步操作啊?你这个需求应该在坚挺某个输入的值变化,然后再调用请求,请求完成之后设置 this.a |
![]() | 39 mamahaha 2019-09-03 13:02:06 +08:00 你这个相当于是暗恋一个人,对方却不知道。 |
![]() | 40 johnnyNg 2019-09-03 13:49:59 +08:00 建议重学 js |
![]() | 41 mikoshu 2019-09-03 17:02:58 +08:00 |
![]() | 42 supuwoerc 2019-09-03 17:05:36 +08:00 终于见到我会的问题了(滑稽) |