不对劲,用了vue2.7 composition-api的 ref 方法,页面怎么不更新?

vue3发布挺久了,目前看在实际业务中使用问题不大,不过对于一些跑得好好的2.x老项目而言,很难直接升到3.x,在不升级 3.x的情况下还想使用 composition-api的话,有两种方式,一是使用 @vue/composition-api,二是直接升级 vue2.7v2.7版本内置了 @vue/composition-api,所以不用手动引入了

本人参与的一个实际业务项目,引入了 vue2.7,但是在使用 ref等响应式 api的时候发现效果与预期不符合,例如下述基于 vue2.7 的代码

<template><div><p>{
  { list[0] }}-{
  { data }}</p><button @click="add">Add</button></div>
</template>

<script>
import { ref } from "vue"

export default {setup() {const list = ref([0])const data = ref(0)return {data,list,add() {list.value[0] = list.value[0] + 1data.value = data.value + 1conosle.log(list.value, data.value)}}}
}
</script> 

当点击 Add按钮的时候,期望 list[0]data 的值自增 1,且页面上展示的值也能同时更新,然而点击之后,控制台打印出来的 list.valuedata.value都没啥问题,但页面上展示的值只有 data 更新了,list[0]却一直固定为初始值,展示出来的值依旧是之前的值,除非我将 list.value指向一个新的地址,页面才能正常更新

add() {list.value[0] = list.value[0] + 1// 重新指定引用地址list.value = list.value.slice()
} 

鄙人不才,之前一直以为只要2.x项目引入了 @vue/composition-api,哪怕底层不一样,用法和表现应该是和 vue3.x差不多才对,但是碰到这个问题后我才意识到二者还是有差别的,因为我的这种写法是比较常见的,作为一个成熟的框架,vue3.x应该不会存在这种问题,然后试了下 vue3.x,相同的写法,确实如我所料,不需要重新指定 list.value的引用地址,页面也能正常更新

已经很长时间没看过源码了,正好借着这个问题简单看下,从源码上搞清楚区别

vue 2.7 的实现

ref 不起作用的原因

源码基于 v2.7.13

问题是由 ref引起的,那么就从它看起

// src/v3/reactivity/ref.ts
export function ref<T extends object>(value: T
): [T] extends [Ref] ? T : Ref<UnwrapRef<T>>
export function ref<T>(value: T): Ref<UnwrapRef<T>>
export function ref<T = any>(): Ref<T | undefined>
export function ref(value?: unknown) {return createRef(value, false)
} 

ref 的类型声明有三个,第一个的意思是如果传入了一个 Ref 类型的参数,则返回这个参数的类型;第二个的意思是传入一个任意类型的参数,返回一个包装了此任意类型的 Ref类型,第三个的意思是可以不传入任何参数,这个时候 ts无法自动推导类型,但你可以传入一个类型来告诉 ts 这个值的类型是什么

// src/v3/reactivity/ref.ts
function createRef(rawValue: unknown, shallow: boolean) {if (isRef(rawValue)) {return rawValue}const ref: any = {}def(ref, RefFlag, true)def(ref, ReactiveFlags.IS_SHALLOW, shallow)def(ref,'dep',defineReactive(ref, 'value', rawValue, null, shallow, isServerRendering()))return ref
} 

createRef中首先判断传入值是不是已经是一个

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值