尤川豪   ·  3年前
445 貼文  ·  275 留言

Vue 與 React 的 event binding 設計哲學差異

我在之前的文章

https://devs.tw/post/368

從 template engine 的角度說明了 vue 跟 react 在設計哲學上的差異

  • vue 希望你好上手,不要有挫折感。

  • react 希望你可以,變成一個優秀的工程師。

今天這篇文章接著從 event binding 作法的不同,這個面向,繼續談談兩種哲學帶來的不同結果。


先舉個簡單的例子,子母元件溝通的情境。

子元件需要更新母元件的狀態(或者說,需要呼叫定義在母元件的函式)。

Vue 的作法

首先在子元件發送 custom event

<button onClick="$emit('increment-counter')">click to increment</button>

在母元件綁定這個事件

<child-component @increment-counter="incrementCounter"></child-component>

在母元件處理這個事件

export default {
  methods: {
    incrementCounter() {
      // you can update the state in the parent,
      // or do anything defined in the parent.
    }
  }
}

vue 這種設計明顯的好處就是,處理 custom event 看起來 syntax 跟處理基本的 html event 一樣

<button @click="doSomething"></button>

<input @change="updateSomething" />

<child-component @increment-counter="incrementCounter"></child-component>

vue 的哲學在這邊表達的就是

來學 vue 吧,面對客製元件以及原生元件的事件,你會用到的 syntax 完全一樣,簡單又優雅吧!

React 的作法

在母元件定義好函式

const incrementCounter = () => {
  //
}

傳給子元件

<div>
  <Child incrementCounter={incrementCounter} />
</div>

在子元件綁定

<button onClick={incrementCounter}></button>

如果從傳統寫 html + jquery 的角度去看 react 這邊會覺得很怪。

怎麼 parent 把自己的任務寫好之後,是傳給 child 自行決定要不要執行?

寫 code 時的思維,到底該上往下還是下往上?感覺 vue 比較好懂?


可是,如果你從 javascript 的語言設計去思考,function 本來就是 first class citizen.

一級公民本來就是可以依照個人喜好,自行定義 function 然後隨意傳來傳去、想在哪執行都可以。

react 在這邊表達的哲學就是:

first class citizen 是一個語言提供的最基礎元素。你想在哪建構、怎麼傳遞、指派給什麼變數、在哪邊呼叫都是你的自由。

光是這種自由就可以簡單做好子母元件溝通,不一定要想成類似 html event 的系統。

你應該要乖乖學好 javascript 對待 function 的方式. 你應該要學習 functional programming philosophy。

React framework 要做的就是:

不妨礙你的任何開發習慣。


上面簡單說明子母元件溝通的範例,可能還是不夠清楚。

感覺兩者差異沒那麼大?更別說 vue 哪有在妨礙你的開發習慣?這說法太過份了吧?

下面我再舉個例子。

假設你在建立某個比較複雜的應用,其中有三個按鈕,分別用三種方式定義按鈕事件。

  1. 定義在元件本身

  2. 從母元件傳來

  3. inline arrow function

Vue 的作法

<button @click="doTask1">John's task 1</button>
<button @click="doTask2">John's task 2</button>
<button @click="() => { alert('This is John\'s task 3.') }">John's task 3</button>
export default {
  methods: {
    doTask1() {
      alert("This is John's task 1.");
    },
    doTask2() {
      this.$emit('custom-event-2') // the actual task is defined in the parent.
    },
  }  
}

注意這邊,第三個按鈕是壞掉的。至於為什麼壞掉,你需要去學習背後的 vue instance 是怎麼運作的。

簡單的說,vue 根本不希望你這樣寫 arrow function。

希望你行為好好寫在 parent 或是 child 的 methods 裡面,不要那麼灑脫,想到哪寫到哪。

React 的作法

const MyComp = ({ taskFromParent }) => {
  const doTask1 = () => {
    alert("This is John's task 1.");
  }

  return (
    <div>
      <button onClick={doTask1}>John's task 1</button>
      <button onClick={taskFromParent}>John's task 2</button>
      <button onClick={() => { alert("This is John's task 3.") }}>John's task 3</button>
    </div>
  )
}

在這個例子例面,我認為 vue 跟 react 的差別天差地遠。

React 想說的就是:

first class function 作為這個語言最基本的元素,developer 想怎樣用就怎樣用。

所以 react developer 分別會有以下評語

關於 task 1:

甚至 function 我想要 const doTask1 寫在 component 的外面都可以。

function 作為一級公民本來想怎麼寫都可以。漂不漂亮交給團隊決定慣例就可以。

何況學好 lexical scope 應該是 javascript developer 的基本。

const doTask1 = () => {
  // define your task event outside of the component
}

const MyComp = ({ taskFromParent }) => {
  return (
    <div>
      <button onClick={doTask1}>John's task 1</button>
      <button onClick={taskFromParent}>John's task 2</button>
      <button onClick={() => { alert("This is John's task 3.") }}>John's task 3</button>
    </div>
  )
}

關於 task 2:

為什麼 custom event name 要因為 HTML’s case-insensitivity 的特性而被迫寫成 kebab-case?

現在是要 javascript 去將就 html 還是 html 去將就 javascript?

如果要將就 html 的話,custom event 有如同 native html event 一樣的 event propagation 機制嗎?

再來,我為什麼需要多去背誦 methods 這個單字,還要把函式寫在這下面?

為什麼要管我的 function 寫在哪?他們是 first class citizen 欸!

關於 task 3:

為什麼在 vue 裡面這樣寫會壞掉?

為什麼我要去學 framework 提供的某種 instance 對我的 scope 跟 this 做了什麼?

此外,就說了雙引號要留給字串,不要在 template engine 裡面用雙引號去寫要 execution 的東西。

現在寫 arrow fucntion 裡面出現字串的時候不方便了吧。

雙引號裡面的單引號裡面的單引號。最後一個引號要用 backslash 去 escape。太麻煩了。


總結起來,我會說,Vue 跟 React 的設計哲學差異就是

  • vue 希望你覺得自己在寫一般的 html 很入門很好寫,然後可以加上一些 javascript 來建構你的應用程式

  • react 希望你覺得自己在寫 javascript,要給你最大的彈性去使用所有最新的 javascript 的 feature

這個結論,也跟 vue 還有 react 社群給人的印象符合

  • vue 支持者:react 好難學喔 光是架環境就好麻煩喔。vue 很快就學會了,也能立刻開始寫我的系統。

  • react 支持者:我們簡直跟著最新的 ECMAScript 每年都在與時俱進、每年都越來越熟悉 functional programming paradigm。所有進階的手法我想怎麼寫就怎麼寫。我沒辦法去寫 vue。

  分享   共 2,766 次點閱
按了喜歡:
共有 0 則留言
還沒有人留言。歡迎分享您的觀點、或是疑問。
您的留言
尤川豪
445 貼文  ·  275 留言

Devs.tw 是讓工程師寫筆記、網誌的平台。隨手紀錄、寫作,方便日後搜尋!

歡迎您一起加入寫作與分享的行列!

查看所有文章