不只 Vue3 , 尤大在 github 還更新了這個
作者:陳大魚頭 github:KRISACHAN
前言
近期前端最火的話題莫過于 Vue v3.0.0 release 的發(fā)布了。
不過除了 Vue 3 之外,魚頭在尤大的 github 上還發(fā)現(xiàn)了悄咪咪上線的DEMO - vue-lit 。
下載下來之后發(fā)現(xiàn)還挺有意思的,所以就來跟大家一起分享下。
正文
項目 README.md 里有這么一句話:
Proof of concept mini custom elements framework powered by @vue/reactivity and lit-html.
由 ?@vue/reactivity 和 lit-html 提供支持的概念性迷你 custom elements (自定義標簽)框架。
下載下來之后發(fā)現(xiàn)這是尤大一個實驗性的玩具DEMO(當然后續(xù)會發(fā)展得如何,那就看尤大了)。
項目目錄如下:

在瀏覽器打開 example.html ,我們能看到:

然后 DEMO 代碼如下(由于代碼太長,本文僅展示部分代碼):
<my-component>my-component>
<script?type="module">
??import?{
????defineComponent,
????reactive,
????html,
????onMounted,
????onUpdated,
????onUnmounted
??}?from?'./index.js'
??defineComponent('my-component',?()?=>?{
????const?state?=?reactive({
??????text:?'hello',
??????show:?true
????})
????const?toggle?=?()?=>?{
??????state.show?=?!state.show
????}
????const?onInput?=?e?=>?{
??????state.text?=?e.target.value
????}
????return?()?=>?html`
??????<button?@click=${toggle}>toggle?childbutton>
??????<p>
??????${state.text}?<input?value=${state.text}?@input=${onInput}>
??????p>
??????${state.show???html`<my-child?msg=${state.text}>my-child>`?:?``}
????`
??})
script>
看到這里就明白了,這是一個讓 Web Components 支持類 Vue 語法的小工具。
我們再來看看源碼(由于代碼太長,本文僅展示除了生命周期以外的核心代碼):
import?{?render?}?from?'https://unpkg.com/lit-html?module'
import?{
??shallowReactive,
??effect
}?from?'https://unpkg.com/@vue/reactivity/dist/reactivity.esm-browser.js'
let?currentInstance
import?{?render?}?from?'https://unpkg.com/lit-html?module'
import?{
??shallowReactive,
??effect
}?from?'https://unpkg.com/@vue/reactivity/dist/reactivity.esm-browser.js'
export?function?defineComponent(name,?propDefs,?factory)?{
??if?(typeof?propDefs?===?'function')?{
????factory?=?propDefs
????propDefs?=?[]
??}
??customElements.define(
????name,
????class?extends?HTMLElement?{
??????static?get?observedAttributes()?{
????????return?propDefs
??????}
??????constructor()?{
????????super()
????????const?props?=?(this._props?=?shallowReactive({}))
????????currentInstance?=?this
????????const?template?=?factory.call(this,?props)
????????currentInstance?=?null
????????const?root?=?this.attachShadow({?mode:?'closed'?})
????????effect(()?=>?{
??????????render(template(),?root)
????????})
??????}
????}
??)
}
export?*?from?'https://unpkg.com/lit-html?module'
export?*?from?'https://unpkg.com/@vue/reactivity/dist/reactivity.esm-browser.js'
這里我們來介紹下這個DEMO所涉及到的五個概念
@vue/reactivity
這是 Vue3 里比較重要的一個模塊,它是 Composition API 的核心,用于實現(xiàn)數(shù)據(jù)響應(yīng)。
shallowReactive
shallowReactive() ?是 Composition API 之一,用于響應(yīng)數(shù)據(jù)的第一層,類似于淺拷貝。
調(diào)用方式如下:
import?{
????shallowReactive,
????isReactive
}?from?'https://unpkg.com/@vue/reactivity/dist/reactivity.esm-browser.js'
const?props?=?shallowReactive({?n:?1?})
console.log(isReactive(props.n))?//?false
console.log(isReactive(props))?//?true
如上所示,props 才是一個 reactive 對象,而 props.n 不是
effect
effect() 則是一個觀察者,調(diào)用方法如下:
import?{
????effect,
????reactive
}?from?'https://unpkg.com/@vue/reactivity/dist/reactivity.esm-browser.js'
let?dummy
const?counter?=?reactive({?num:?0?})
effect(()?=>?(dummy?=?counter.num))
console.log(dummy?===?0)?//?true
counter.num?=?7
console.log(dummy?===?7)?//?true
lit-html
距 官網(wǎng) 介紹,它是一個高效,富有表現(xiàn)力,可擴展性的 HTML 模板。它支持創(chuàng)建跟更新 DOM,也兼容所有的瀏覽器。
使用方式如下:
import?{
????html,
????render
}?from?'https://unpkg.com/lit-html?module'
let?sayHello?=?(name)?=>?html`<h1>Hello?${name}h1>`
render(sayHello('World'),?document.body)
render(sayHello('Everyone'),?document.body)
這個時候頁面就會渲染出一個 ,效果如下:Hello Everyone

還挺好用,不過網(wǎng)上對其褒貶不一,有興趣的可以去搜索引擎搜一搜,本文不作展開。
Web Components
至于 Web Components 應(yīng)該是老生常談的技術(shù)了,簡單來說就是原生的組件化技術(shù),簡單的例子如下:
<h1><context-span>examplecontext-span>h1>
<script?src="./wc.js">script>
//?wc.js
class?ContextSpan?extends?HTMLElement?{
????constructor()?{
??????super();
??????const?style?=?document.createElement('style');
??????const?span =?document.createElement('span');
??????span.textContent?=?this.textContent;
??????const?shadowRoot?=?this.attachShadow({mode:?'open'});
??????shadowRoot.appendChild(style);
??????shadowRoot.appendChild(span);
??????style.textContent?=?`
????????span:hover?{?text-decoration:?underline;?}
????????:host-context(h1)?{?font-style:?italic;?}
????????:host-context(h1):after?{?content:?"?-?我是一個H1"?}
????????:host?{?background:?rgba(0,0,0,0.1);?padding:?2px?5px;?}
??????`;
????}
}
customElements.define('context-span',?ContextSpan);
效果如下:

vue-lit
我們回到 vue-lit 來,vue-lit 有可能只是尤大一時興起的玩具,但是也有可能是 vue 結(jié)合 原生組件的第一步。
在 Vue 跟 React 此類前端框架出來不久之后,Web Components 就應(yīng)運而生,雖然直到如今地位還不能跟這些前端框架相比,但是 Web Components 始終是瀏覽器的一大發(fā)展,極有可能就取代眾多前端框架成為新的開發(fā)模式,畢竟當年 JQuery 大火之后,瀏覽器也出了許許多多模擬它 API 的原生函數(shù)。
所以看到這個工具,魚頭也是非常激動,雖然不確定后續(xù)會如何發(fā)展,但是對于在 Web Components 里使用 Vue 的這種模式,還是非常期待的。
后記
如果你喜歡探討技術(shù),或者對本文有任何的意見或建議,非常歡迎加魚頭微信好友一起探討,當然,魚頭也非常希望能跟你一起聊生活,聊愛好,談天說地。魚頭的微信號是:krisChans95 也可以掃碼關(guān)注公眾號,訂閱更多精彩內(nèi)容。
