1. 程式人生 > 程式設計 >關於vue3預設把所有onSomething當作v-on事件繫結的思考

關於vue3預設把所有onSomething當作v-on事件繫結的思考

最近在重新看vue3的rfcs,發現一個細節,原話如下:

props that start with on are handled as v-on bindings,with everything after on being converted to all-lowercase as the event name (more on this below)

也就是說,以後如果你在傳遞props的時候,以 on 開頭的props,如果在元件上沒有做props的宣告,那麼會被當作事件繫結到元件的根節點上。

究其原因,我大致概括了兩點:

  • 相容vue2中的v-on.native
  • vue3的vnode宣告把props拍平了,為了區分事件和其他props,就統一把所有的on開通的props預設作為事件繫結

為此,我開了一個issue來討論這個問題,issue地址 。我關心的主要有兩點:

  • 這是對functional component的嚴重限制
  • 是否會導致一些令人括困惑的誤解

先講第一點

vue3中可以直接通過 function() {} 來宣告函式元件了,這是一個便利性的非常大的提升。在以前,你要宣告元件,你必須要:

{
  functinal: true,props: {},render() {}
}

這最大的提升來自不需要宣告props,為什麼說這是提升,因為這讓我們開發HOC變得更方便了。現在我們可以通過 ...rest 的方式把HOC不關心的props直接向下傳遞了。

但是現在因為這個預設限制,我們不得不在HOC中宣告所有可能的他要擴充套件的元件以 on 開頭的props。舉個例子,我們有如下元件:

{
  props: {
    name: String,onChange: Function
  }
}

而我們的HOC的功能是在 name 前面加上 prefix ,對於這個HOC我們需要關心的只是 name 和他自己的props: prefix 。所以他的宣告應該如下:

{
  props: {
    name: String,prefix: String
  }
}

然後在render中他可以這麼做:

{
  render() {
    const {name,prefix,...rest} = props
    return <WrapperedComponent name={`${prefix}-${name}`} {...rest} />
  }
}

也就是對於HOC來說,他是不需要關心他擴充套件的元件其他的props的,但是在這種情況下,如果我們不在HOC中宣告,那麼在使用的時候傳入的 onChange 會自動繫結到root節點,而不是作為props傳遞下去。

第二點:令人困惑的使用

舉個例子,如果我有一個元件:

{
  props: {
    onChange: Function
  },methods: {
    handleInput() {
      // do someting
      // 並且根據情況觸發`onChange`
    } 
  },render() {
    return <input onInput={this.handleInput} />
  }
}

很顯然我是想要封裝 input 的變化,在滿足某些條件的時候才對外丟擲新的value。但是如果這個時候有人就是不看文件,直接傳遞了 onInput ,那麼這時候 input 事件會直接繫結到節點上,那麼這也是可以觸發的。

如果我們的測試用例太少或者不仔細,很可能反應不過來他們的區別。這顯然是作為元件開發者的我們不希望出現的,但我們又無法限制這種行為。

總結

不得不說,我在考慮這兩個問題的時候是有一定的 React思維 在裡面的。因為個人來說我是比較喜歡React的API設計的,非常的簡潔,其對於元件的使用也更趨於極致,就是一切皆元件(連 redirect 這樣的行為都定義成了元件)。

而vue是一直在跟隨react的,相信這點大家也不會否認。vue3更新的hooks(Composition)API,Suspense等明顯是借鑑的React的概念。

但同時我又是很看好vue3的,我一直覺得vue2這樣的API設計以及 .vue 檔案的開發模式都是為了吸引中低階使用者而準備的,甚至捨棄了一些高階API特性(比如HOC在vue中就很難實現,並且普及率相當低)。

而vue3的hooks API以及其對JSX的更好支援,還有更純粹的 functional component ,讓我一度看到了vue在工程方面更激進的變化。

但是 v-on 的預設行為,卻又是一次那麼明顯的 替使用者做決定 的行為。其實要解決這個問題很簡單,可以完全不考慮 v-on ,把所有傳遞的引數作為props,如果元件開發者真的要在根節點上繫結事件,他可以實現的時候繫結,我們不應該在使用元件的場景下需要考慮在元件內部的節點上做一些事情,這樣做的副作用實在太大了。

雖然目前看來尤老師會聽取我的意見的可能性是非常小的,但我還是抱有一點簡單的期望吧。

到此這篇關於關於vue3預設把所有onSomething當作v-on事件繫結的思考的文章就介紹到這了,更多相關vue3 onSomething當作v-on事件繫結內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!