瘋狂的 Vue3 之 四個函式寫應用

Ljzn發表於2021-04-21

只用四個函式, 不需要熟悉 JavaScript 各種奇怪的知識, 不需要複雜的配置, 就可以立刻寫出比較複雜的前端頁面. 一開始我也不相信, 但 Vue3 真的做到了. 而且很神奇的一點是, 在 Vue3 的架構裡我發現了很多類似 elixir/erlang 的地方.

createApp

對於母語是 elixir/erlang 的程式設計師來說, App(lication) 是很熟悉的概念: 廣義上值整個虛擬機器中的一個基本獨立的應用, 狹義上指實現了 Application behaviour 的模組. Vue 中的 App 比 elixir/erlang 的更加獨立一些, 但實現方式很類似, 只要實現一個對應的回撥函式即可.

import { createApp, h } from 'vue'
const hello = (props, context) => h('div', null, 'hello vue3')

createApp(hello)
.mount('#app')

等價 html:

<div>hello vue3</div>

App 的回撥函式需要的返回值是一個 vnode, 即 vue 中虛擬的 html dom元素; 另外這個函式會傳入兩個引數, 其中 property 即是該 vnode 所接收的屬性, 例如 <div id="app"></div> 裡面的 id 就是一個屬性. context 則提供了一系列該 vnode 可用的 vue 內建方法.

和 elixir/erlang 非常類似的還有: Vue App 可以 mountunmount , erlang application 可以 startstop .

h

在上面的例子裡, 我們使用了 h 函式來創造 vnode, 一般這個函式被稱為 "渲染函式". 它能接收三個引數, 分別是: component, attributes 和 slots. 它非常類似 elixir/erlang 裡的 GenServer.start(modelue, init_arg, options \\ []).

在上面的例子中, 我們實際上使用了簡略寫法去設定 vnode 的內容(slots), 完整的寫法是:

h('div', null, {
  default: (props) => 'hello vue3'
})

使用完整寫法可以幫我們在某些元件的指定位置使用自定義的 slot 模板.

resolveComponent

這裡我們使用了基本的元件 div. 對與在第三方庫裡的其他元件, 就需要先使用 resolveComponent 來尋找對應的元件的具體函式入口. 例如我們使用 ant-design-vuea-button 元件:

import antd from 'ant-design-vue'
import { createApp, h, resolveComponent } from 'vue'

const hello = (props, context) => h(resolveComponent('a-button'), null, 'hello vue3')

createApp(hello)
.mount('#app')

等價 html:

<a-button>hello vue3</a-button>

reactive

利用上面三個函式, 我們已經可以使用任意的元件創造靜態頁面, 而 reactive 函式才是 Vue3 真正的魔法所在, 使用它可以很方便地讓頁面動起來. 再次類比到 elixir/erlang, 我們知道程式之間一般不共享資料, 除非使用 ETS 這樣的記憶體資料庫. 而 reactive 函式不僅可以幫我們在vnode 之間共享資料, 還以在資料被更新時立刻同步到每個 vnode.

const model = reactive({text: ''})

const input = () => h('input', {onInput: (e) => model.text = e.target.value}) // 繫結 onInput 事件, 在有輸入時更新 model.text

const show = () => h('p', null, model.text) // 使用 model.text 的值

const app = (_p, _c) => h('div', null, [
  input(),
  show()
])

createApp(app)
  .mount('#app')

等價 html:

<input />
<p>這裡的內容會隨 input 自動更新</p>

注意, 這裡的 inputshow 都需要是函式, 因為其在 model 被更新時都會被重複呼叫. 如果寫成了表示式, 則不會動態更新.

結語

使用以上四個基本函式, 就可以自由地呼叫和組合第三方元件庫, 寫出可用的動態前端頁面了.

相關文章