vue新ref语法糖争议

近日,Vue 发明人尤雨溪在 Vue RFCs 下提交了一份新的 Ref 语法糖提案,该提案一经发布便引来了不少争议。

提案内容
这份提案就是在单文件组织(SFC)中引入一个新的script 标签写法,写法为

关于为什么这样做?尤雨溪表示,一方面是通过自动暴露顶级变量可以减少代码的冗余度;另一方面,通过 ref: 语法可以让 ref 更高效。

具体案例
例如这样的 HTML 代码:

引发争议
针对以上改动,Github 上持反对意见用户较多:

在这里插入图片描述

在这里插入图片描述
大家可以前往:https://github.com/vuejs/rfcs/pull/222 看老外们对这一改动的反馈。

尤雨溪回复
目前 GitHub 上的反馈似乎偏负面,对此尤雨溪在知乎上进行了回复,原文地址:https://www.zhihu.com/question/429036806/answer/1564223482

RFC本身加上原帖里的回复我已经写了大概快上万字的英语了,但看起来知乎很多回答应该是没看完就急着发表意见了,所以还是用中文针对一些常见的疑问和误解解释一下。

看上去不像 JavaScript

ref: count = 1 使用的是标签语法,在 syntax 层面是合法的 JavaScript,而且在非严格模式下是可以正常执行的,甚至语义也是声明了一个名为 count 的全局变量。同时这也是合法的 TypeScript 语法,不会和类型声明混淆(类型声明必然需要 let 和 const)当然这里确实只是语法层面的合法,实际上等于是给 ref: 这个标签赋予了一个不同的语义。标签语法本身是一个极少被使用的功能,实际使用也都是用于标记循环声明(用在 for/while 前面),像例子中 ref: count = 1 这样的用法,其原始语义是毫无用处的,这也是为什么我们认为牺牲这个原始语义来获得响应式的变量声明是一个值得的交换。

为什么用标签语法而不是直接发明新语法

使用标签语法确实是受到了 Svelte 的启发。根本原因在于和 JS 保持 syntax 层面的完全兼容能够尽可能保证现有的 JS 工具生态对接。标签语法能够正确地被 Babel,TS parser/transformer(如 esbuild/swc),Prettier,ESLint 以及任何 IDE 的 JavaScript 语法高亮所直接支持,只有在涉及语义的情况下,如类型推导和 ESLint 变量相关规则才需要针对性的兼容。如果用一个全新的非标准语法,就意味着需要在 parser 层面对上述所有工具进行修改,基本不可行。

类型推导的问题 RFC 里也有专门讨论,有兴趣的可以看原文,这里不赘述。

感觉心智负担变重了

虽然底层是编译到 ref() 的语法糖,但其实对于新人来说根本不需要知道 ref() 的存在就可以使用,因为在不需要获取底层 ref 对象的场景下,通过 ref: 声明的变量心智模型和用 let 声明的变量的心智模型完全一致。你就把 ref: 当成一个响应式的 let 就行了。这个模型已经足够实现大部分入门级别的功能,只有到进阶之后开始学习逻辑抽取复用时,才需要知道 ref() 的概念。

对于已经学习了 Composition API 的用户来说会觉得 “又多了一个概念”,同时由于 RFC 事无巨细地讨论了编译的规则,会产生一种 “心智负担增加了” 的错觉。其实我很久以前用 CoffeeScript,Babel,或是刚开始用 TS 的时候,也有这样的感觉,因为我喜欢用之前先看看这东西编译出来是个什么样子。结果就是看过了这个之后用着上层语法,脑子里忍不住去把它转换成底层语法。但这本质上是我们的大脑在习惯了底层思维方式之后的一种惯性。这种惯性在使用新语法一段时间之后很快就消失了,我们的大脑适应能力还是很强的。如果你开始就不 care 编译出来是个什么结果,就更不会有这个问题(你用 nullish coalescing 或者 decorator 的时候会去想着 babel/TS 编译出来是个什么结果么?)

对于从零开始的用户来说,如上所述 ref: 就是一个能触发响应的 let 而已,学习成本是很低的。具体可以看一个对比:

Options API

也可以看一下一个已经实际使用该语法的用户的代码和他的使用体验:https://github.com/vuejs/rfcs/pull/222#issuecomment-723500871

其他一些疑问

review 时没办法一眼看出来这是普通变量还是ref变量。

Vetur 可以给 ref: 声明的变量加上不同的高亮。

在 SFC里用 ref: 语法糖,日后想把逻辑抽到 .ts/.js 中时,又要改成 ref()的形式。这两种风格的不一致也影响了重构的效率。

由于编译转换规则非常简单直接,Vetur 可以提供这样的工作流:选择代码块 -> 右键 “compile ref sugar” -> 剪切 -> 黏贴。可以提供双向转换,完全机械操作,几乎没有脑力损耗。需要一提的是 Svelte 的响应编译模型无法解决这个问题,因为 Svelte 编译出来的代码不是给人维护的代码,且和组件上下文强绑定,所以没法挪到组件外部。这也顺便回答了 “既然都要语法糖了为什么不像 Svelte 那样走完全编译路线“。

这里不否认组件内外风格的切换是会有额外的心智成本的,但这是否能够接受可能会因人而异。因此,ref:语法糖完全是可选的,可以通过编译选项强制关闭。不喜欢的话依然可以在

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浩星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值