如题,demo 代码如下,模拟读取后端 api 返回:
使用 data.value 可以获取到数据,但是使用 list?.value 获取不到数据,问了 gpt 也问不出如何使用
const {data:list}
开头的代码进行解构,难道 ref 就没法解构吗
![]() | 1 shakaraka PRO 你不如把 data 和 list 打印出来比比看,就知道怎么回事了 |
![]() | 2 linkopeneyes 280 天前 ![]() 你的 list 只拿到初始默认 data 的 undefined ,你如果想让 list 时刻随着 data 响应应该用计算属性 |
![]() | 3 bgm004 280 天前 先学一下 js 吧,const {data:list} 这一行执行的时候 你的 ref 还是 undefined 。 |
![]() | 4 heishu &nsp;280 天前 我猜你找的是 computed |
![]() | 5 dadaji 280 天前 via iPhone 为什么我看见 any 想喷人 |
![]() | 6 shintendo 280 天前 鉴定为 react 写多了 |
7 zhhbstudio 280 天前 toRef 也可以解决 const list = toRef(data, 'data') toRefs 主要是 reactive 的属性转 ref ,这个可以直接解构 |
![]() | 8 tyrone2333 280 天前 @dadaji anyscript 怎么你了 |
9 zhengfan2016 OP @shintendo 确实,react 写多了,看到 vue 一长串可选链就想改成 react 的解构写法,之前 vue 转过来的同事就很喜欢写一长串的可选链 |
10 zhengfan2016 OP |
11 zhengfan2016 OP @zhhbstudio 这个一行只能一个变量,我想找能在一行解构多个变量并保持响应式的写法, 类似 react 这样的:const {code,data,message} = xxx || {} 这样,这样一行就定义三个变量, 而不是 vue const code = data?.value?.code; const list= data?.value?.data ; const message = data?.value?.message; 这样的写法,这样写比较嗦。 |
12 zhhbstudio 279 天前 @zhengfan2016 const data = reactive({list: null, code: null, message: null}) 接口返回后挨个赋值 用的时候直接 data.code data.list 也能转 ref ,但不推荐 const {code ,list} = toRefs ( data ) code.value 每个框架有自己的写法习惯,你非要把 react 的拿过来会很不舒服的 找俩 star 多的 vue3 开源看看他们怎么处理的接口返回吧 |
![]() | 13 ooo4 278 天前 试试这个 const data = reactive({ code: null, data: [] }) onMounted(() => { setTimeout(() => { Object.assign(data, { code: 0, data: [666, 777, 888] }) }, 1000) }) function useFoo(state) { const res = {} watchEffect(() => { for (let key in state) { res[key] = toRef(state, key) } }) return res } const { data: list } = useFoo(data) watchEffect(() => { console.log('data', data) console.log('list', list) }) |
![]() | 14 ooo4 278 天前 @ooo4 不需要这么麻烦 ``` import { reactive, watchEffect, onMounted, toRefs } from 'vue'; const data = reactive({ code: null, data: [] }) onMounted(() => { setTimeout(() => { Object.assign(data, { code: 0, data: [666, 777, 888] }) }, 1000) }) const { data: list } = toRefs(data) watchEffect(() => { console.log('list', list.value.length) }) ``` |
![]() | 15 ooo4 278 天前 ![]() toRefs 的参数必须是一个对象才行,而且必须还要存在属性,因为它要把对应的属性值变成 ref 。 而现在使用的是 ref 包裹数据,那么也应该是`const {data:list} = toRefs(data.value)`才行,让 list 变成了响应式数据, 但是是通过`data.value = { code: 0, data: [666, 777, 888] }`改变数据,也只是改变了 data(ref),list 并没有改变,所以 list 还是以前的数据,如果这样`Object.assign(data.value, { code: 0, data: [666, 777, 888] })`修改数据应该可以 看错了 [如果对 ref 包装的 obj 进行解构] ``` import { reactive, watchEffect, onMounted, toRefs, ref } from 'vue'; const data = ref({ code: null, data: [] }) onMounted(() => { setTimeout(() => { Object.assign(data.value, { code: 0, data: [666, 777, 888] }) }, 1000) }) debugger const { data: list } = toRefs(data.value) watchEffect(() => { console.log('list', list.value) }) ``` |
![]() | 16 Outshine 278 天前 看了代码,我寻思 `react` 里你这代码也不能这样用啊。 你这 `list` 并不是响应式数据,因为此时 `data` 为 undefined ,那么就会结构后面的 {},{} 里面没有 `data` 这个键(实际里面有没有这个键 list 都不是响应式) ```Javascript const { data: list } = toRefs<any>(data) || {} ``` |
18 zhengfan2016 OP @ooo4 #15 感谢,试过了代码确实能正常运行,但我发现了两个问题,一个是 reactive 默认值必须填入{ code: null, data: [] },哪怕是{ code: undefined, data: undefined}也是 ok 。而去掉其中任何一个 key 或者把 reactive 置为 undefined 都会导致不能正常运行。 另一个就是 Object.assign(data.value, { code: 0, data: [666, 777, 888] })这行必须要有,没有这行也会导致代码不能正常运行。这行确实没看懂,我看 mdn 的介绍和用 data.value 修改效果理论上应该是一样的 |
![]() | 19 ooo4 277 天前 @zhengfan2016 因为 setup 函数不是副作用,所以不会重新执行,那么 toRefs 的数据在没有其他副作用的情况下,是不会改变的 如果保持你的代码,那么只能改渲染函数了,让他尽量的像 react ``` // Comp.js 不是 sfc import { watchEffect, onMounted, toRefs, ref } from 'vue'; export default { setup() { let data = ref() onMounted(() => { setTimeout(() => { data.value = { code: 0, data: [666, 777, 888] } }, 1000) }) return () => { // 渲染函数 这是副作用,当响应式数据改变了,就会重新执行 const { data: list } = toRefs(data.value) || {} watchEffect(() => { console.log('list', list?.value) }) // jsx return 1 } } } ``` |
![]() | 20 jiangzm 277 天前 用 reactive 定义, 用 toRefs 结构。 这么简单为啥讨论这么多 |
![]() | 21 Outshine 276 天前 @zhengfan2016 #17 不是,你这段代码在 react 里相当于 const { value } = useRef(undefined) || {} 而不是你举例这个。 --- 另外,解决方案参考 #20 @jiangzm 的,vue 文档里也讲过这个。 |