等等,这样讨论vue ref-sugar是不讲武德的!

广告位招租
扫码页面底部二维码联系

我们讨论ref-sugar本质上在讨论三件事:设计原则,开发体验,实现魔法

【本文首发于唐霜的博客】【未经授权禁止转载】【版权所有,侵权必究】

我们现在在该问题上争论,很多人直接从第三【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】点出发,认为实现魔法不好,但实际上,根源转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。在于第一点,vue3发布的ref没有遵循【本文受版权保护】转载请注明出处:www.tangshuang.netvue原有的设计原则,使得变量的使用在s未经授权,禁止复制转载。【转载请注明来源】cript和template中呈现了两种【作者:唐霜】【本文首发于唐霜的博客】形态。

【版权所有,侵权必究】【未经授权禁止转载】【版权所有】唐霜 www.tangshu【本文受版权保护】本文版权归作者所有,未经授权不得转载。ang.net转载请注明出处:www.tangshua【原创内容,转载请注明出处】【作者:唐霜】ng.net
export default {
  setup() {
    const count = ref(0)
    const plus = (inc) => count.value += inc // 脚本中使用 count.value
    return { count, plus }
  }
}

<div>{{ count }}</div> // 模板中使用 count

设计原则

Vue的设计原则包含两个基本点:1.通过【作者:唐霜】本文作者:唐霜,转载请注明出处。直接修改状态变量而非调用接口完成响应式,【原创内容,转载请注明出处】【转载请注明来源】2.接近原始js变量操作而非复杂操作的0【作者:唐霜】【版权所有,侵权必究】成本理解。简单说就是,vue帮你封装好响转载请注明出处:www.tangshuang.net【本文受版权保护】应式,你只要无脑使用,做到真正0心智模型本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】。但在ref这个点上,0心智失效了,因为原创内容,盗版必究。本文作者:唐霜,转载请注明出处。我们在脚本中经常忘记.value。

【原创内容,转载请注明出处】【作者:唐霜】

对问题的解决,不能超出设计原则,这是vu本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.nete所坚守的,超出原则的设计,比如这篇文章,虽然可以解决问题,但是一旦泛滥,那【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】么vue就没啥价值了。

本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】ng.net【未经授权禁止转载】
既然在书写时,你经常忘记写.value,本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】那我接下来就让你忘记变得合法合理,所以新著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。的ref提案的目标,就是隐藏.value著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。,让你继续0心智。那就涉及到一个开发体验【本文受版权保护】转载请注明出处:www.tangshuang.net的问题了,究竟怎么让开发者写代码,才爽呢未经授权,禁止复制转载。【转载请注明来源】
原创内容,盗版必究。【版权所有】唐霜 www.tangshu本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.netang.net未经授权,禁止复制转载。

开发体验

在开发体验道路上分出了两条岔路,AoT和【本文首发于唐霜的博客】【未经授权禁止转载】Runtime。前者把活交给编译过程,能【本文受版权保护】【原创不易,请尊重版权】力实现全靠工具,但是可以随意发明语法,想【未经授权禁止转载】原创内容,盗版必究。怎么玩都可以,爽,缺点就是脱离了那套编译著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net工具跑不了,典型就是svelte。后者需著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net要自己写一套基于原始js能力的系统实现效未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net果,提供接口,按照接口文档用就完事了,浏【未经授权禁止转载】本文作者:唐霜,转载请注明出处。览器里面随便跑,缺点是运行时代码加大,心原创内容,盗版必究。【原创内容,转载请注明出处】智负担加剧(要记住用法)。

著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。

vue想尽一切办法在两者之间做平衡,几年【关注微信公众号:wwwtangshuangnet】【本文受版权保护】来,长期坚持能够纯runtime实现,还【原创内容,转载请注明出处】【转载请注明来源】是干不过js语言本身的限制。所以,新提案本文版权归作者所有,未经授权不得转载。【作者:唐霜】ref-sugar妥协了,是纯粹的AoT未经授权,禁止复制转载。未经授权,禁止复制转载。实现方案。当然,AoT也可以在浏览器端搞原创内容,盗版必究。本文作者:唐霜,转载请注明出处。编译,就像当年less搞的一样,但很明显【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】,这是歧途,自己在浏览器里面解释执行js【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。是不明智的,太不安全了。

本文作者:唐霜,转载请注明出处。【作者:唐霜】【版权所有,侵权必究】

对该方案的喷点,多多少少是由于这个原因。本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。因为如果把解决问题的方法丢给编译器去解决未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net,那还有啥是编译器不能解决的?

著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】【转载请注明来源】转载请注明出处:www.tangshua原创内容,盗版必究。原创内容,盗版必究。ng.net

所以,能够平息这次风波的根本解决办法,一【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net定是:0心智负担+runtime的方案。连尤大都掉坑的问题,是不是无解了呢?接【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】下来看看实现魔法。

【未经授权禁止转载】转载请注明出处:www.tangshua未经授权,禁止复制转载。转载请注明出处:www.tangshuang.netng.net【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】ang.net【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。【本文受版权保护】et 获取更多精彩内容】

实现魔法

我想,尤大掉坑的根源,可能是对设计原则的转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】误解,认为vue必须是基于单一方案实现响【未经授权禁止转载】转载请注明出处:www.tangshuang.net应式,所谓单一方案,就是vue里面只能有转载请注明出处:www.tangshuang.net【作者:唐霜】数据拦截这一套方案。但是,响应式方案真不【原创内容,转载请注明出处】原创内容,盗版必究。止数据拦截这一条路。vue1,2采用了d转载请注明出处:www.tangshuang.net原创内容,盗版必究。efineProperty方案实现响应式【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】,而vue3采用了Proxy,开发者的心著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net智没有任何负担,反而叫好,这说明,问题的【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。根源不在于实现响应式的内部细节,而在最终【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。表现出来的效果。

【访问 www.tangshuang.n【作者:唐霜】本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】本文作者:唐霜,转载请注明出处。

所以,为什么vue只能基于单一方案实现响原创内容,盗版必究。本文作者:唐霜,转载请注明出处。应式?为什么不能同时用两套响应式方案?在【作者:唐霜】未经授权,禁止复制转载。ref这个点上,脏检查机制就是一个赠送的【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net方案。(这想法不是我提的

【版权所有】唐霜 www.tangshu【本文受版权保护】【版权所有】唐霜 www.tangshuang.netang.net【版权所有】唐霜 www.tangshu【转载请注明来源】未经授权,禁止复制转载。ang.net本文版权归作者所有,未经授权不得转载。
let a = ref(0, () => a) 
function handle() { 
    a = a + 1 
}
<div @click="handle">{{ a }}</div>
【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。
 上面代码里面的关键点在于ref的第二个未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】参数,这个参数返回a,这样,每次在进行重未经授权,禁止复制转载。【原创内容,转载请注明出处】新计算(如被依赖的情况下)时,都读取a这未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。个变量,将采用a最新的值,包括watch【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。,也会使用这第二个函数作为被watch对原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。象是否变化的依据。
【版权所有】唐霜 www.tangshu本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.netang.net【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】ngnet】本文版权归作者所有,未经授权不得转载。【本文受版权保护】

另外,js里面有一些魔法可以用上了,主要本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】是valueOf和Symbol.toPr转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】imitive,这两个属性可以帮助我们完本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】成对象的值运算。我简单举个例子你就能明白【原创不易,请尊重版权】原创内容,盗版必究。其中的道理。

【访问 www.tangshuang.n【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.netet 获取更多精彩内容】【转载请注明来源】【作者:唐霜】本文版权归作者所有,未经授权不得转载。
var a = {
  value: 1,
  valueOf() { return this.value },
}

var b = {
  value: 2,
  valueOf() { return this.value },
}

接下来我们做这个运行:a + b得到的结【本文首发于唐霜的博客】原创内容,盗版必究。果是3.我们还可以修改a.value =【版权所有】唐霜 www.tangshuang.net【转载请注明来源】 2,再执行a + b结果是4. 道理就【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】是这么简单。let a = ref(0,转载请注明出处:www.tangshuang.net原创内容,盗版必究。 () => a) 中,a的结果是本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。一个如上结构的对象,所以参与运行是OK的【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net,对a.value进行改造,就可以做依赖【未经授权禁止转载】本文作者:唐霜,转载请注明出处。收集了。比如:

【转载请注明来源】【转载请注明来源】转载请注明出处:www.tangshua原创内容,盗版必究。本文作者:唐霜,转载请注明出处。ng.net原创内容,盗版必究。
let c = computed(() => a + b)

由于上面式子中会调用a.value和b.【版权所有】唐霜 www.tangshuang.net【作者:唐霜】value,所以可以知道c对a,b有依赖【未经授权禁止转载】原创内容,盗版必究。。下面是最关键的:

原创内容,盗版必究。本文作者:唐霜,转载请注明出处。
a = a + 1

对a重新赋值,此时a的数据类型发生了变化原创内容,盗版必究。【本文首发于唐霜的博客】,从对象变成了数字。但是没有关系,在co【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。mputed进行依赖收集时,我们已经得到著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。了一个计算公式:

【作者:唐霜】【版权所有,侵权必究】【版权所有,侵权必究】
c = (() => a)() + (() => b)()

也就是说,无论a, b是什么数据类型,计原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】算后得到的c的结果是确定的。而关键的问题原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。在于,一旦a丢失了object类型,就没【原创内容,转载请注明出处】【作者:唐霜】有办法依靠vue的响应式设计完成响应式效【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】果。此时,脏检查就来了。

未经授权,禁止复制转载。未经授权,禁止复制转载。未经授权,禁止复制转载。
  • 用callback包装handle(效果【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】类似computed,主要做依赖收集):转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】 handle = callback((【本文受版权保护】本文版权归作者所有,未经授权不得转载。) => a = a + 1)
  • 【原创内容,转载请注明出处】转载请注明出处:www.tangshua【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.netng.net【原创不易,请尊重版权】【访问 www.tangshuang.n著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】et 获取更多精彩内容】
  • 执行handle时,a.value被收集【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】,代表handle函数有可能对a产生副作【版权所有】唐霜 www.tangshuang.net【作者:唐霜】用,每次执行handle,可能收集到的r著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。ef变量不同,由if…els【本文首发于唐霜的博客】未经授权,禁止复制转载。e决定,根据这个情况,还可以做一些优化
  • 未经授权,禁止复制转载。【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。
  • 当handle被调用结束时,对收集到的所【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】有依赖进行检查,检查依据是上一个值和这一【作者:唐霜】【版权所有】唐霜 www.tangshuang.net次的() => a结果
  • 【作者:唐霜】原创内容,盗版必究。
  • 当发现值不相等时,表示依赖被更新了,此时【版权所有,侵权必究】原创内容,盗版必究。回溯所有computed,如果发现对a有【原创不易,请尊重版权】原创内容,盗版必究。依赖,那么对应computed属性需要被【本文受版权保护】本文版权归作者所有,未经授权不得转载。更新
  • 【作者:唐霜】【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。【本文受版权保护】

和angularjs的脏检查不同,因为这转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】里我可以明确知道自己依赖了哪些变量,所以著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。我做的检查范围会小很多。而且由于next【版权所有,侵权必究】【原创内容,转载请注明出处】Tick机制的存在,脏检查也仅限于数据层【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。面,不会触发DOM的更新。

【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。ang.net【本文受版权保护】

结束

你看,仅仅给ref加了第二个参数,就可以著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】把这个issue给结了。但是,你可能会说【作者:唐霜】原创内容,盗版必究。,我() => a真不想写啊!!!未经授权,禁止复制转载。【未经授权禁止转载】要解决这个问题,最好的办法,就是你去做T【转载请注明来源】原创内容,盗版必究。C39主席,然后强推PrimitiveP【原创内容,转载请注明出处】【版权所有,侵权必究】roxy,并且让Proxy完全适用于Pr【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。imitiveProxy,这下世界安静了本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。

【本文受版权保护】未经授权,禁止复制转载。