學(xué)不完的框架,舔不完的面,Qwik,你到底想干啥
最近我又又雙學(xué)習(xí)了一個新框架,qwik
真的沒完沒了了,
不過作為"前端娛樂圈戰(zhàn)地記者",我繼續(xù)幫大家踩雷。
?? 同系列閱讀
- 學(xué)不完的框架,??啄不完的米,SolidJS,你到底愛誰???
- ??超級簡單的Svelte,學(xué)不會你來打我
- 真心希望不會有燒不斷地鎖這篇文章!!!
?? 初識qwik
廢話不多說,我們先上代碼。一個簡單的計數(shù)器功能
?? useSignal
const App = component$(() => {
const count = useSignal(0);
return (
<>
<button onClick$={() => count.value++}>+</button>
<div>{count.value}</div>
</>
);
});
讓我們給這個計數(shù)器加上監(jiān)聽事件(后面會詳細(xì)講)
useVisibleTask$(({ track }) => {
track(() => console.log(count.value))
})
sigal.gif
useSignal,雖然讓我想起來了熟悉地SolidJS,但是看寫法,這不就是vue3的ref嗎?是的,看起來很像,那有沒有類似reactive呢?
?? useStore
當(dāng)然有啊,useSignal是針對基本變量的。對于非基本類型可以使用useStore。
const App = component$(() => {
const data = useStore({count: 0})
return (
<>
<button onClick$={() => data.count++}>+</button>
<p>{data.count}</p>
</>
);
});
sigal.gif
useStore可以提供方法,不過比較復(fù)雜:
import {
$,
type QRL
} from "@builder.io/qwik";
type Store = {
count: number
add: QRL<(this: Store) => void>
}
const App = component$(() => {
const data = useStore<Store>({
count: 0,
add: $(function(this) {
this.count++;
})
})
return (
<>
<button onClick$={() => data.add()}>+</button>
<p>{data.count}</p>
</>
);
}
sigal.gif
?? useComputed$
reactive有了,computed是不是也應(yīng)該有啊,來了,它就是useComputed$
const capitalizedName = useComputed$(() => {
return count.value + 'mmdctjj';
});
useVisibleTask$(({ track }) => {
track(() => console.log(capitalizedName.value))
})
computer.gif
?? useContext
那依賴注入有沒有啊?抱歉,沒有,因為qwik是基于jsx的框架,所以只有拿useContext來將就了
type Store = {
count: number
add: QRL<(this: Store) => void>
}
// ?? 創(chuàng)建全局的上下文
const context = createContextId<Store>('uuid')
const App = component$(() => {
const data = useStore<Store>({
count: 0,
add: $(function(this)
this.count++;
})
})
// ?? provider數(shù)據(jù)
useContextProvider(context, data);
return (
<>
<button onClick$={() => data.add()}>+</button>
<p>{data.count}</p>
</>
);
}
const Child = component$(() => {
// ?? 消費上下文
const data = useContext(context)
return (
<>
<Child />
</>
);
}
好吧,接下來我們說些不一樣的
?? useTask$ or useVisibleTask$
上面的例子中,我們所有的監(jiān)聽事件都是通過useVisibleTask$實現(xiàn)的。雖然它看起來和useEffect類似,但是卻有著很大的區(qū)別。
這得從qwik的架構(gòu)說起,首先qwik是個服務(wù)端渲染的框架,相當(dāng)于Next.js(基于React服務(wù)端渲染框架)、 Nuxt.js(基于Vue地服務(wù)端渲染框架),換句話說,它天生支持服務(wù)端渲染的前端框架。所以一個組件的生命周期是從服務(wù)器開始的。
useTask$ -------> RENDER ---> useVisibleTask$
|| --- SERVER or BROWSER --- | ----- BROWSER ----- ||
pause|resume
它們都是用來注冊任務(wù)的鉤子函數(shù),這個任務(wù)在服務(wù)端僅僅執(zhí)行一次,在客戶端可能多次渲染。
下面是具體的區(qū)別
?? useTask$
useTask$首先在服務(wù)端執(zhí)行一次,如果客戶端使用track訂閱依賴了,那么當(dāng)客戶端渲染之后觸發(fā)更新時,任務(wù)會在客戶端再次執(zhí)行。如果沒有track,那么僅僅在客戶端執(zhí)行一次。
const App = component$(() => {
const count = useSignal(0);
useTask$(({ track }) => {
track(() => console.log(count.value))
})
return (
<>
<button onClick$={() => count.value++}>+</button>
<div>{count.value}</div>
</>
);
});
task.gif
頁面刷新后服務(wù)端也執(zhí)行了一次任務(wù)
?? useVisibleTask$
useVisibleTask$:僅僅在瀏覽器執(zhí)行,渲染之后立馬執(zhí)行,當(dāng)訂閱的參數(shù)發(fā)生改變時,任務(wù)會被再次執(zhí)行。
const App = component$(() => {
const count = useSignal(0);
useVisibleTask$(({ track }) => {
track(() => console.log(count.value))
})
return (
<>
<button onClick$={() => count.value++}>+</button>
<div>{count.value}</div>
</>
);
});
taskvis.gif
它們還有一個特別重要的參數(shù)cleanup,每次新的任務(wù)被觸發(fā)時,都會執(zhí)行上次任務(wù)的cleanup。另外組件被移除時也會被執(zhí)行。
useVisibleTask$(({ track, cleanup }) => {
// console.log('I am excuted!')
track(() => console.log(count.value))
cleanup(() => console.log('last'))
})
cleanup.gif
我們可以看到,每次任務(wù)觸發(fā)都是先打印last,然后才是最新的count.value
另外,還有一個重要的配置項:{ strategy: 'document-ready' },此時,會在頁面加載完畢立馬執(zhí)行。
useVisibleTask$(() => {
// 渲染完畢之后執(zhí)行
console.log(2222)
})
useVisibleTask$(() => {
// document-ready立馬執(zhí)行
console.log(1111)
}, { strategy: 'document-ready' })
此時console的打印結(jié)果是先1111,然后是2222。
?? 幫它模擬完整的生命周期
綜上,我們可以模擬出一個完整的生命周期,
唯一的瑕疵是before update會在組件銷毀時和unmount一起執(zhí)行一次。
useVisibleTask$(() => {
console.log('before mounted!')
}, { strategy: 'document-ready' })
useVisibleTask$(({ cleanup }) => {
console.log('mounted!')
cleanup(() => console.log('unmount'))
})
useVisibleTask$(({ track, cleanup }) => {
track(() => console.log('updated!', count.value))
cleanup(() => console.log('before update'))
})
?? 總結(jié)
qwik上線一年不到已經(jīng)17.9k地star了,足見它地優(yōu)秀了!