VUE 新語法糖魔改 JavaScript 引爭議

2020-12-12 開源中國

近日,VUE 作者尤雨溪在社區意見徵求稿(RFC) 上提交了一份 Ref 語法糖的提案,引發了社區的爭議。

簡要地說,這份提案在單文件組件(SFC)中引入了一個新的 script 標籤寫法,寫法為 <script setup> ,這種寫法會自動將所有頂級變量聲明暴露給模板(template)使用。同時在 <script setup> 中引入了一個消除 ref 的 value 屬性的語法糖,該語法糖在編譯期間自動將語法糖轉為正常代碼。

例如這樣的 HTML 代碼:

<script setup>// 聲明一個會被編譯到 ref 的變量ref: count = 1function inc() { // 該變量可像普通的值一樣使用,無需 .value count++}// 用 $ 前綴對應原始的 ref 對象console.log($count.value)</script><template> <button @click="inc">{{ count }}</button></templat

就會被編譯成這樣:

<script setup>import { ref } from 'vue'export default { setup() { const count = ref(1) function inc() { count.value++ } console.log(count.value) return { count, inc } }}</script><template> <button @click="inc">{{ count }}</button></templ

注意 label: x = 1 仍是有效的 JS 語法(即帶標籤的賦值語句,相當於直接對 x 賦值,嚴格模式下如果 x 未定義則會報錯),相當於特殊處理了 ref 標籤名的語義。

為什麼要這樣做?

尤雨溪表示,一方面是通過自動暴露頂級變量可以減少代碼的冗餘度;另一方面,通過 ref: 語法可以讓 ref 更高效。

自從 Composition API 誕生以來,大家就一直在討論到底用 ref 好還是用 reactive 對象好。用 ref 會導致代碼中到處都是 .value ,而且如果開發者沒有使用 TypeScript,還會經常漏寫 .value ,所以很多開發者不知道該怎麼處理 ref。

實際上 ref 的存在是因為 JS 這門語言存在一些問題:如果不把一個值封裝在一個對象裡,就無法通過 JS 自帶的方法把這個值變成一個響應式的數據。這意味著如果不魔改 JS 的語義,就不可能像是用普通變量那樣使用 ref。此外,尤雨溪也承認自己是從 Svelte 框架得到了啟發,Svelte 早前就魔改了 JS 的語義, export let $ 的語義都被 Svelte 賦予了更強大更方便的功能。

「以前我們希望儘量維持 JS 原本的語義不變,因為魔改 JS 會帶來一些問題,但是總需要有「第一個吃螃蟹」的人,對 JS 進行改造,給開發者提供更好的開發體驗。」尤雨溪說。

引發爭議

針對這一提案,很多社區用戶留言表示反對,大多數人反對的原因還是集中在這一提案對 JavaScript 魔改太嚴重 ,質疑為什麼用標籤語法而不是直接發明新語法,讓用戶的心智負擔加重了等等。

針對這些質疑,尤雨溪本人也一一做出了回應:

關於魔改 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 層面對上述所有工具進行修改,基本不可行。

感覺心智負擔變重了

雖然底層是編譯到 ref() 的語法糖,但其實對於新人來說根本不需要知道 ref() 的存在就可以使用,因為在不需要獲取底層 ref 對象的場景下,通過 ref: 聲明的變量心智模型和用 let 聲明的變量的心智模型完全一致。用戶只需要把 ref: 當成一個響應式的 let 就行了。這個模型已經足夠實現大部分入門級別的功能,只有到進階之後開始學習邏輯抽取復用時,才需要知道 ref() 的概念。

對於已經學習了 Composition API 的用戶來說會覺得 「又多了一個概念」,同時由於 RFC 事無巨細地討論了編譯的規則,會產生一種 「心智負擔增加了」 的錯覺。其實我很久以前用 CoffeeScript,Babel,或是剛開始用 TS 的時候,也有這樣的感覺,因為我喜歡用之前先看看這東西編譯出來是個什麼樣子。結果就是看過了這個之後用著上層語法,腦子裡忍不住去把它轉換成底層語法。但這本質上是我們的大腦在習慣了底層思維方式之後的一種慣性。這種慣性在使用新語法一段時間之後很快就消失了,我們的大腦適應能力還是很強的。如果你開始就不 care 編譯出來是個什麼結果,就更不會有這個問題(你用 nullish coalescing 或者 decorator 的時候會去想著 babel/TS 編譯出來是個什麼結果麼?)

對於從零開始的用戶來說,如上所述 ref: 就是一個能觸發響應的 let 而已,學習成本是很低的。

尤雨溪回答原文:https://www.zhihu.com/question/429036806/answer/1564223482

最後,尤雨溪表示在這個 RFC 提案發表之前自己就知道會引起很多爭議,也非常理解人們面對新技術的第一反應是「不能接受」。不過他也表示提案未必就會實裝,希望大家討論的時候保持理性,同時建議大家完整看完 RFC 全文和 GitHub 上的討論後再提出質疑。

完整 RFC :https://github.com/vuejs/rfcs/blob/script-setup/active-rfcs/0000-script-setup.md

相關焦點

  • 基於Vue實現一個有點意思的拼拼樂小遊戲
    本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫前言為了加深大家對vue的了解和vue項目實戰,筆者採用vue生態來重構此項目,方便大家學習和探索。
  • Javascript 生成器
    生成器語法因語言而異。Javascript 的生成器語法類似於 PHP,但是區別也很大,如果你希望它們的作用相同,那麼最終你會感到非常困惑。 在 javascript 中,如果想要使用生成器,則需要: 定義特殊的生成器函數 調用該函數創建一個生成器對象 在循環中使用該生成器對象,或直接調用其 方法 我們以下面這個簡單的程序做為起點,並執行以下每個步驟:
  • javascript中那些奇怪的特性
    它充滿了神秘的語法和過時的功能。 我已經使用 JavaScript 多年了,迄今為止,我仍時不時地發現一些我從未知道的隱藏語法或技巧。比如下圖,讓很多前端程式設計師感到很無奈。(前提是您不需要將任何參數傳遞給構造函數)下面的代碼樣式都被認為是有效的JS語法,並且會給你完全相同的結果!構造函數括號是可選的可以跳過立即調用的函數表達式括號對於我來說,立即調用的函數表達式的語法總是有點奇怪.所有括號都有什麼用?
  • slot vue - CSDN
    Reference Listhttps://cn.vuejs.org/v2/guide/components-slots.htmlSlot的作用語法小提示:由slot的標籤就是子組件,有
  • javascript這些特點你知道其中幾個?建議前端小白好好看看!
    javascript示圖1、解釋性的腳本語言怎麼理解解釋性的腳本語言?解釋性腳本語言就是執行是不需要編譯,即每個javascript語句執行的時才翻譯,跟編譯型語言不一樣。 javascript語法特點跟c、c++等相似,但是這些語言需要先編譯。 javascript這個特點可以跟html很好結合,大大增加網站互動性。
  • 如何使用JavaScript實現前端導入和導出excel文件
    1.2 實現一鍵導入excel文件並生成table表格導入excel文件的功能我們可以用javascript原生的方式實現解析, 比如可以用fileReader這些原生api,但考慮到開發效率和後期的維護, 筆者這裡採用antd的Upload組件和XLSX來實現上傳文件並解析的功能.
  • VUE 項目如何快速優化?|原力計劃
    通過 vue.config.js修改webpack的默認配置通過vue-cli 3,0 工具生成的項目,默認隱藏了所有的 webpack配置項,目的是為了屏幕項目的配置過程,讓程式設計師的工作重心放到具體的功能和邏輯的實現上。
  • slot vue 用法專題及常見問題 - CSDN
    最近發布不久的Vue 2.6,使用插槽的語法變得更加簡潔。 對插槽的這種改變讓我對發現插槽的潛在功能感興趣,以便為我們基於Vue的項目提供可重用性,新功能和更清晰的可讀性。 真正有能力的插槽是什麼?如果你是Vue的新手,或者還沒有看到2.6版的變化,請繼續閱讀。也許學習插槽的最佳資源是Vue自己的文檔,但是我將在這裡給出一個綱要。
  • Vue的異步更新實現原理
    講道理,如果不在vue裡,單獨運行這段程序的話,輸出一定是從1到100,但是為什麼在vue中就不一樣了呢?nextTick原理派發更新大家都知道vue的響應式的靠依賴收集和派發更新來實現的。nextTick源碼接著打開vue2.x的源碼,目錄core/util/next-tick.js,代碼量很小,加上注釋才110行,是比較好理解的。
  • Vue.js布局
    動態Vue.js布局組件前言vue.js是漸進增強的視圖庫,可以作為.html頁面部分使用,也可以結合vue-router、vuex、axios用來構建單頁面或多頁面應用。
  • Vue 3全新的Web開發構建工具——Vite介紹
    不過Vite項目的默認配置文件是vite.config.js,而不是vue.config.js。>"scripts": {"dev": "vite","build": "vite build"},"dependencies": {"vue
  • vue網頁聊天室|Vue+ElementUI仿微信界面
    項目介紹基於vue2+vuex+vue-cli+element-ui+swiper等技術開發仿微信pc端界面聊天應用,實現了發送消息+表情(動圖gif)、圖片/視頻預覽、右鍵長按菜單、紅包/朋友圈、截圖發送等功能。
  • vue的插槽用法 - CSDN
    slot也是同樣地作用,留下一定的空間,每個人使用的時候單獨定義自己的功能模塊(3) 值得注意的是:在 Vue 2.6.0 中,為具名插槽和作用域插槽引入了一個新的統一的語法 (即 v-slot 指令)。它取代了 slot 和 slot-scope 這兩個目前已被廢棄但未被移除且仍在文檔中的 attribute。1.
  • 20個常用的JavaScript簡寫技巧
    箭頭函數 參考:JavaScript Arrow function https://jscurious.com/javascript-arrow-function/ 8. 模板字符串 我們一般使用 + 運算符來連接字符串變量。
  • Vue-count-to(數字滾動計時)
    在實際開發過程中會遇到這種情況:可以看到這裡的數字需要一個滾動的效果這種效果我們可以通過vue-count-to插件來實現實現流程:1.安裝在控制臺輸入npm install vue-count-to來安裝vue-count-to插件2.
  • 芒果臺狂改歌詞字幕,再次引爭議
    芒果臺狂改歌詞字幕,再次引爭議 蔡徐坤是人氣熱度話題度都非常高娛樂圈新人,出道後他也一直潛心研究音樂。最近他似乎把重心放到了綜藝節目上,參與了《跑男》的錄製。在音樂上,很久已經沒有新作品了。最近推出了歌曲《情人》,也讓粉絲們激動不已。不過前幾天,蔡徐坤與章若楠合作《情人》MV的事情又在網絡上引起部分粉絲的不滿。
  • 3.2.2 JavaScript中do-while循環語句的使用
    其語法格式如下:do{語句組} while(表達式);參數說明:1)語句組:用來指定需要重複執行的語句,即循環體,可以是一條或多條語句。代碼如下:<script type="text/javascript">var sum=0;var i=1;do{sum+=i;
  • 安妮·萊博維茨拍攝Vogue新封面引爭議
    安妮·萊博維茨拍攝Vogue新封面引爭議 2020-07-23 12:18 來源:澎湃新聞·澎湃號·湃客
  • 漫畫《DEATH NOTE》新短篇結局引爭議
    漫畫《DEATH NOTE》新短篇結局引爭議在上周曾為大家介紹過,由大場鶇原作、小畑健作畫的漫畫《DEATH NOTE》將要推出新短篇的消息。目前,本作的草稿已經在Jump+上公開。這次的新作結局同樣引發了網友們的爭議。
  • 3.2.3 JavaScript中for循環語句的使用
    其語法格式如下:for(初始化語句,條件表達式,迭代語句){語句組}參數說明:1)初始化語句:一般用來對循環變量進行初始化賦值。代碼如下:<script type="text/javascript">var sum=0;for(var i=1;i<=100;i++){sum+=i; //相當於