摘要:讓人又愛(ài)又恨的微信小程序自微信小程序以下簡(jiǎn)稱小程序誕生以來(lái),就伴隨著贊譽(yù)與爭(zhēng)議不斷。同時(shí)于開(kāi)發(fā)者來(lái)說(shuō),小程序的生態(tài)不斷在完善,許多的坑已被踩平,雖然還是存在一些令人詬病的問(wèn)題,但已經(jīng)足見(jiàn)微信的誠(chéng)意了。
Taro 介紹
在互聯(lián)網(wǎng)不斷發(fā)展的今天,前端程序員們也不斷面臨著新的挑戰(zhàn),在這個(gè)變化多端、不斷革新自己的領(lǐng)域,每一年都有新的美好事物在發(fā)生。從去年微信小程序的誕生,到今年的逐漸火熱,以及異軍突起的輕應(yīng)用、百度小程序等的出現(xiàn),前端可以延伸的領(lǐng)域已經(jīng)越來(lái)越廣,當(dāng)然也意味著業(yè)務(wù)在不斷擴(kuò)大。這時(shí)候,如何通過(guò)技術(shù)手段來(lái)提升開(kāi)發(fā)效率,應(yīng)對(duì)不斷增長(zhǎng)的業(yè)務(wù),京東前端凹凸實(shí)驗(yàn)室開(kāi)源多 Taro 就此誕生。讓人又愛(ài)又恨的微信小程序
自 2017-1-9 微信小程序(以下簡(jiǎn)稱小程序)誕生以來(lái),就伴隨著贊譽(yù)與爭(zhēng)議不斷。從發(fā)布上線時(shí)的不被大多數(shù)人看好,到如今的逐漸火熱,甚至說(shuō)是如日中天也不為過(guò),小程序用時(shí)間與實(shí)踐證明了自己的價(jià)值。同時(shí)于開(kāi)發(fā)者來(lái)說(shuō),小程序的生態(tài)不斷在完善,許多的坑已被踩平,雖然還是存在一些令人詬病的問(wèn)題,但已經(jīng)足見(jiàn)微信的誠(chéng)意了。這個(gè)時(shí)候要是還沒(méi)有上手把玩過(guò)小程序,就顯得非常OUT了。
小程序?qū)τ谇岸顺绦騿T來(lái)說(shuō)應(yīng)該算得上是福音了,用前端相關(guān)的技術(shù),獲得絲般順滑的 Native 體驗(yàn)。小程序給前端程序員打開(kāi)了一扇新的大門,大家都應(yīng)該感謝微信,但是從開(kāi)發(fā)的角度來(lái)說(shuō),小程序的開(kāi)發(fā)體驗(yàn)就非常值得商榷了,不僅語(yǔ)法上顯得有些不倫不類,而且有些莫名其妙的坑也經(jīng)常讓人不經(jīng)意間感嘆,從市面上層出不窮的小程序開(kāi)發(fā)框架就可見(jiàn)一斑。以下就盤(pán)點(diǎn)部分小程序開(kāi)發(fā)的痛點(diǎn)。
代碼組織與語(yǔ)法在小程序中,一個(gè)頁(yè)面 page 可能擁有 page.js、page.wxss、page.wxml 、page.json 四個(gè)文件
這樣在開(kāi)發(fā)的時(shí)候就需要來(lái)回進(jìn)行文件切換,尤其是在同時(shí)開(kāi)發(fā)模板和邏輯的時(shí)候,切來(lái)切去會(huì)顯得尤其麻煩,影響開(kāi)發(fā)效率。
而在語(yǔ)法上,小程序的語(yǔ)法可以說(shuō)既像 React ,又像 Vue,不能說(shuō)顯得有點(diǎn)不倫不類,但在使用上總是感覺(jué)有些別扭,對(duì)于開(kāi)發(fā)者來(lái)說(shuō),等于又要學(xué)習(xí)一套新的語(yǔ)法,提升了學(xué)習(xí)成本。而且,小程序的模板由于沒(méi)有編輯器插件的支持,書(shū)寫(xiě)的時(shí)候也沒(méi)有智能提示與 lint 檢查,書(shū)寫(xiě)起來(lái)顯得有些麻煩。
命名規(guī)范在小程序中到處可見(jiàn)規(guī)范不統(tǒng)一的情況
例如組件的屬性,以最簡(jiǎn)單的 button 組件為例,在小程序官方文檔中,該組件的屬性部分截圖如下
button 組件
屬性名既有以中劃線分割多個(gè)單詞的情況 session-form,也有多個(gè)單詞連寫(xiě)的情況 bindgetphonenumber。當(dāng)然這也不是最嚴(yán)重的,你可以說(shuō)事件綁定的規(guī)范就是 bind + 事件名 ,而其他屬性的規(guī)范就是中劃線分割單詞,然而這并不是作為標(biāo)準(zhǔn)
progress 組件
這不統(tǒng)一的標(biāo)準(zhǔn)使得開(kāi)發(fā)者體驗(yàn)極其難受。
同樣的情況也出現(xiàn)在 頁(yè)面 與 組件 的生命周期方法中,頁(yè)面 的生命周期方法有 onLoad、onReady、onUnload 等,但到了 組件 中則是 created、attached 、ready 等,這樣規(guī)范又不統(tǒng)一了,為啥 頁(yè)面 的生命周期方法是 on+Xxx 的格式,但到了 組件 里卻不一樣了呢,讓人費(fèi)解。
開(kāi)發(fā)方式小程序官方提供了 微信開(kāi)發(fā)工具 作為開(kāi)發(fā)編譯工具,而對(duì)于代碼本身沒(méi)有提供一個(gè)類似 webpack 的工程化開(kāi)發(fā)工具,來(lái)解決開(kāi)發(fā)中的一些問(wèn)題,所以小程序原生的開(kāi)發(fā)方式顯得不那么現(xiàn)代化,這也是很多小程序開(kāi)發(fā)框架致力于解決的問(wèn)題。例如,在小程序開(kāi)發(fā)中
不能使用 npm 管理依賴,在小程序中需要手動(dòng)把第三方代碼文件下載到本地,然后再 reuqire 進(jìn)行使用,顯得不那么優(yōu)雅
不能使用 Sass 等 CSS 預(yù)處理器,由于沒(méi)有預(yù)編譯的概念,小程序開(kāi)發(fā)中無(wú)法使用市面上流行的 CSS 預(yù)處理器,這樣會(huì)使得樣式代碼難以管理
不完整的 ES Next 語(yǔ)法支持,小程序默認(rèn)只能支持極少一部分 ES6 規(guī)范的語(yǔ)法,而 ES 是不斷往前發(fā)展的,一些非常優(yōu)秀的新語(yǔ)法特性就不能使用了
手動(dòng)的文件處理,像圖片壓縮、代碼壓縮等等的一些文件操作,必須手工來(lái)處理,顯得有些繁瑣
以上就是從開(kāi)發(fā)者的角度看到的一些小程序的開(kāi)發(fā)問(wèn)題,不過(guò)縱然有千般困難,我們總要面對(duì),作為新時(shí)代的前端開(kāi)發(fā)工程師,我們不能一味忍受問(wèn)題,要保持技術(shù)的頭腦,以技術(shù)作為武器,用技術(shù)手段去提升的我們開(kāi)發(fā)體驗(yàn)。
能不能用React來(lái)寫(xiě)小程序目前前端界言及前端框架,必離不開(kāi)依然保持著統(tǒng)治地位的 React 與 Vue,這兩個(gè)都是非常優(yōu)秀的前端 UI 框架,而且在網(wǎng)上也經(jīng)常能看到兩個(gè)框架的粉絲之間熱情交流,碰撞出一些思想火花,顯得社區(qū)異常活躍。
而我們團(tuán)隊(duì)也在去年勇敢地拋棄了歷史包袱,非常榮幸地引入了 React 開(kāi)發(fā)方式,讓我們團(tuán)隊(duì)丟掉了煤油燈,開(kāi)始通上了電。而且也研發(fā)出了一款優(yōu)秀的類 React 框架 Nerv ,讓我們和 React 開(kāi)發(fā)思想結(jié)合得更深。
與小程序的開(kāi)發(fā)方式相比,React 明顯顯得更加現(xiàn)代化、規(guī)范化,而且 React 天生組件化更適合我們的業(yè)務(wù)開(kāi)發(fā),JSX 也比字符串模板有更強(qiáng)的表現(xiàn)力。那么這時(shí)候我們就在思考,我們能不能用 React 來(lái)寫(xiě)小程序?
類比
通過(guò)對(duì)比體驗(yàn) 小程序和 React ,我們還是能發(fā)現(xiàn)兩者之間相似的地方
生命周期
小程序的生命周期和 React 的生命周期,在很大程度上是類似的,我們甚至能找到他們之間的對(duì)應(yīng)關(guān)系
app 及頁(yè)面的生命周期
可以看出,對(duì)于 app 及 頁(yè)面 來(lái)說(shuō),除了 onShow 與 onHide 兩個(gè)方法,其他方法都能在 React 中找到對(duì)應(yīng)。
數(shù)據(jù)更新方式
在 React 中,組件的內(nèi)部數(shù)據(jù)是用 state 來(lái)進(jìn)行管理的,而在小程序中組件的內(nèi)部數(shù)據(jù)都是用 data 來(lái)進(jìn)行管理,兩者具有一定相似性。而同時(shí)在 React 中,我們更新數(shù)據(jù)使用的是 setState 方法,傳入新的數(shù)據(jù)或者生成新數(shù)據(jù)的函數(shù),從而更新相應(yīng)視圖。在小程序中,則對(duì)應(yīng)的有 setData 方法,傳入新的數(shù)據(jù),從而更新視圖。
兩者都是以數(shù)據(jù)驅(qū)動(dòng)視圖的方式進(jìn)行更新,而且 api 神似。
事件綁定
小程序中綁定事件使用的是 bind + 事件名 的方式,例如點(diǎn)擊事件,小程序中是 bindtap
1
而在 React 里,則是 on + 事件名 的方式,例如點(diǎn)擊事件, React web 中是 onClick
1
雖然看上去不一樣,但其實(shí)是可以類比的,我們只需要在編譯時(shí)將 on + 事件名 的形式編譯成 bind + 事件名 的形式就可以了。
如此看來(lái),兩者之間有些相似,用 React 來(lái)寫(xiě)小程序貌似是可行的,但接下來(lái)我們就發(fā)現(xiàn)了巨大的差異。巨大的差異
React 與小程序之間最大的差異就是他們的模板了,在 React 中,是使用 JSX 來(lái)作為組件的模板的,而小程序則與 Vue 一樣,是使用字符串模板的。這樣兩者之間就有著巨大的差異了。
JSX
render () { return ({this.state.list.map((item, idx) => ( ) }{item} ))}
小程序模板
{{item}} 走你
眾所周知,JSX 其實(shí)本質(zhì)上就是 JS,我們可以在里面寫(xiě)任意的邏輯代碼,這樣一來(lái)就比字符串模板的表現(xiàn)力與操作性要強(qiáng)多了,況且,小程序的字符串模板功能比較羸弱,只有一些比較基本的功能。那這樣的話,要如何來(lái)實(shí)現(xiàn)用 JSX 來(lái)寫(xiě)小程序模板呢。
編譯原理的力量我們可以仔細(xì)來(lái)分析我們的需求,我們期望使用 JSX 來(lái)書(shū)寫(xiě)小程序模板,但小程序顯然是不支持執(zhí)行 JSX 代碼的(要是支持的話,Taro 應(yīng)該也就不存在了吧),我們也不能期望微信能給我們開(kāi)個(gè)后門來(lái)跑 JSX。那么這個(gè)時(shí)候我們就想,我們要是能夠?qū)?JSX 編譯成小程序模板就好了。
事實(shí)上在我們平時(shí)的開(kāi)發(fā)中,這種編譯的操作到處可見(jiàn),babel 就是我們最常用的 JS 代碼編譯器,一般瀏覽器是不能支持一些非常新的語(yǔ)法特性的,但我們又想使用它們,這個(gè)時(shí)候就可以借助 babel 來(lái)將我們的高版本的 ES 代碼,編譯成瀏覽器可以運(yùn)行的 ES 代碼。而我們像要將 JSX 編譯成小程序模板,也是同樣的道理。我們首先來(lái)了解一下 Babel 的運(yùn)行機(jī)制。
Babel 作為一個(gè) 代碼編譯器 ,能夠?qū)?ES6/7/8 的代碼編譯成 ES5 的代碼,其核心利用的就是計(jì)算中非常基礎(chǔ)的編譯原理知識(shí),將輸入語(yǔ)言代碼,通過(guò)編譯器執(zhí)行,輸出目標(biāo)語(yǔ)言的代碼。編譯原理的一般過(guò)程就是,輸入源程序,經(jīng)過(guò)詞法分析、語(yǔ)法分析,構(gòu)造出語(yǔ)法樹(shù),再經(jīng)過(guò)語(yǔ)義分析,理解程序正確與否,再對(duì)語(yǔ)法樹(shù)做出需要的操作與優(yōu)化,最終生成目標(biāo)代碼。
Babel 的編譯過(guò)程亦是如此,主要包含三個(gè)階段
解析過(guò)程,在這個(gè)過(guò)程中進(jìn)行詞法、語(yǔ)法分析,以及語(yǔ)義分析,生成符合 ESTree 標(biāo)準(zhǔn) 虛擬語(yǔ)法樹(shù) AST
轉(zhuǎn)換過(guò)程,針對(duì) AST 做出已定義好的操作,babel 的配置文件 .babelrc 中定義的 preset 、 plugin 就是在這一步中執(zhí)行并改變 AST 的
生成過(guò)程,將前一步轉(zhuǎn)換好的 AST 生成目標(biāo)代碼的字符串
為了更好地理解這些過(guò)程,大家可以利用 Ast Explorer 這個(gè)網(wǎng)站接一下自己的代碼,感受一下每一部分代碼所對(duì)應(yīng)的 AST 結(jié)構(gòu)。
可以看到,一份源碼經(jīng)過(guò)編譯器解析后,會(huì)變成類似如下的結(jié)構(gòu)
{ type: "Program", start: 0, end: 78, loc: { start, end } sourceType: "module", body: [ { type: "VariableDeclaration", ... }, { type: "VariableDeclaration", ... }, { type: "FunctionDeclaration", ... }, { type: "ExpressionStatement", ... } ] ... }
其中,body 里包含的就是我們示例代碼的語(yǔ)法樹(shù)結(jié)構(gòu),第一個(gè) VariableDeclaration 對(duì)應(yīng)的是 const a = 1,第三個(gè) FunctionDeclaration 對(duì)應(yīng)的則是 function sum (a, b) { },分別就是 JS 中的變量定義與函數(shù)定義,每一個(gè)樹(shù)節(jié)點(diǎn)里都會(huì)包含許多子節(jié)點(diǎn),這樣就形成了一個(gè)樹(shù)形結(jié)構(gòu),更多的節(jié)點(diǎn)類型,請(qǐng)參考 babel types。
當(dāng)然我們?cè)谶@兒只是簡(jiǎn)單介紹下編譯原理與 babel,編譯原理是一門非常深?yuàn)W的課程, babel 也是一個(gè)非常優(yōu)秀的工具,希望在后續(xù)的文章中能和大家再詳細(xì)探討這一部分內(nèi)容。
再次回到我們的需求,將 JSX 編譯成小程序模板,非常幸運(yùn)的是 babel 的核心編譯器 babylon 是支持對(duì) JSX 語(yǔ)法的解析的,我們可以直接利用它來(lái)幫我們構(gòu)造 AST,而我們需要專注的核心就是如何對(duì) AST 進(jìn)行轉(zhuǎn)換操作,得出我們需要的新 AST,再將新 AST 進(jìn)行遞歸遍歷,生成小程序的模板。
JSX 代碼
{this.props.counter.num}
編譯生成小程序模板
{{counter.num}}
以上僅僅是轉(zhuǎn)換規(guī)則的冰山一角,JSX 的寫(xiě)法極其靈活多變,通過(guò)窮舉的方式,將常用的、React 官方推薦的寫(xiě)法作為轉(zhuǎn)換規(guī)則加以支持,而一些比較生僻的,或者是不那么推薦的寫(xiě)的寫(xiě)法則不做支持,轉(zhuǎn)而以 eslint 插件的方式,提示用戶進(jìn)行修改。目前我們支持的 JSX 轉(zhuǎn)換規(guī)則,大致能覆蓋到 JSX 80% 的寫(xiě)法操作。
多端發(fā)布輸入一份源代碼,針對(duì)不同的端設(shè)定好對(duì)應(yīng)的轉(zhuǎn)換規(guī)則,再一鍵轉(zhuǎn)換出對(duì)應(yīng)端的代碼。而且由于我們已經(jīng)遵循 React 語(yǔ)法了,那我們?cè)俎D(zhuǎn)成 H5 端(使用 Nerv)與 RN 端(使用 React)也就有了天然的優(yōu)勢(shì)
設(shè)計(jì)思路但是仔細(xì)思考我們又會(huì)發(fā)現(xiàn),僅僅將代碼按照對(duì)應(yīng)語(yǔ)法規(guī)則轉(zhuǎn)換過(guò)去后,還遠(yuǎn)遠(yuǎn)不夠,因?yàn)椴煌藭?huì)有自己的原生組件,端能力 API 等等,代碼直接轉(zhuǎn)換過(guò)去后,可能不能直接執(zhí)行。例如,小程序中普通的容器組件用的是 view ,而在 H5 中則是 div;小程序中提供了豐富的端能力 API,例如網(wǎng)絡(luò)請(qǐng)求、文件下載、數(shù)據(jù)緩存等,而在 H5 中對(duì)應(yīng)功能的 API 則不一致。
所以,為了彌補(bǔ)不同端的差異,Taro 需要訂制好一個(gè)統(tǒng)一的組件庫(kù)標(biāo)準(zhǔn),以及統(tǒng)一的 API 標(biāo)準(zhǔn),在不同的端依靠它們的語(yǔ)法與能力去實(shí)現(xiàn)這個(gè)組件庫(kù)與 API,同時(shí)還要為不同的端編寫(xiě)相應(yīng)的運(yùn)行時(shí)框架,負(fù)責(zé)初始化等等操作。通過(guò)以上這些操作,就能實(shí)現(xiàn)一份一鍵生成多端的需求了。在 Taro 最初的設(shè)計(jì)中,我們組件庫(kù)與 API 的標(biāo)準(zhǔn)就是源自小程序的,既然已經(jīng)有定義好的組件庫(kù)與 API 標(biāo)準(zhǔn),那為啥不直接拿來(lái)使用呢,這樣不僅省去了定制標(biāo)準(zhǔn)的冥思苦想,同時(shí)也省去了為小程序開(kāi)發(fā)組件庫(kù)與 API 的麻煩,只需要讓其他端來(lái)向小程序靠齊就好。
可能有些人會(huì)有疑問(wèn),既然是為不同的端實(shí)現(xiàn)了對(duì)應(yīng)的組件庫(kù)與端能力 API (小程序除外,因?yàn)榻M件庫(kù)和 API 的標(biāo)準(zhǔn)都是源自小程序),那么是怎么能夠只寫(xiě)一份代碼就夠了呢?因?yàn)槲覀冇芯幾g的操作,在書(shū)寫(xiě)代碼的時(shí)候,只需要引入標(biāo)準(zhǔn)組件庫(kù) @tarojs/components 與運(yùn)行時(shí)框架 @tarojs/taro ,代碼經(jīng)過(guò)編譯之后,會(huì)變成對(duì)應(yīng)端所需要的庫(kù)。
既然組件庫(kù)以及端能力都是依靠不同的端做不同實(shí)現(xiàn)來(lái)抹平差異,那么同樣的,如果想為 Taro 引入更多的功能支持的話,有時(shí)候也需要按照這個(gè)套路來(lái)。例如,為了提升開(kāi)發(fā)便利性,我們?yōu)?Taro 加入了 Redux 支持,做法就是,在小程序端,實(shí)現(xiàn) @tarojs/redux 這個(gè)庫(kù)來(lái)作為小程序的 Redux 輔助庫(kù),并且以他作為基準(zhǔn)庫(kù),它具有和 react-redux 一致的 API,在書(shū)寫(xiě)代碼的時(shí)候,引用的都是 @tarojs/redux ,經(jīng)過(guò)編譯后,在 H5 端會(huì)替換成 nerv-redux(Nerv的 Redux 輔助庫(kù)),在 RN 端會(huì)替換成 react-redux。這樣就實(shí)現(xiàn)了 Redux 在 Taro 中的多端支持。
Taro 項(xiàng)目官網(wǎng):https://taro.aotu.io/
Taro GitHub:https://github.com/NervJS/taro
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/102871.html
摘要:開(kāi)發(fā)前需要安裝和以及一些需要用到的中間件如果在要使用的話,還需要引入這個(gè)庫(kù)或者使用示例下面通過(guò)實(shí)現(xiàn)一個(gè)快速上手。然后開(kāi)始創(chuàng)建處理這兩個(gè)指令的。完成上述三步之后,我們就可以在應(yīng)用的主頁(yè)使用相應(yīng)修改并取得新的數(shù)據(jù)了。 本文適合有一定React和Redux基礎(chǔ)的用戶閱讀。 前言的前言 最近被一款來(lái)自京東凹凸實(shí)驗(yàn)室的多終端開(kāi)發(fā)框架Taro吸粉了,官方對(duì) Taro 的簡(jiǎn)介是使用React語(yǔ)法,一...
摘要:其他的項(xiàng)目使用了拼裝樣式驗(yàn)證傳入的屬性是否是函數(shù)驗(yàn)證父組件傳入的數(shù)據(jù)格式是否正確五參考文獻(xiàn)談?wù)劦氖褂檬褂脠?chǎng)景 仿 taro-ui 實(shí)現(xiàn) modal 組件 小程序組件. 簡(jiǎn)介: 項(xiàng)目中使用到彈窗類的組件,重新制造了一個(gè)輪子. 源碼地址: https://github.com/xiangxiong... 編寫(xiě)完modal組件總計(jì)花了28分鐘. 效果圖: showImg(htt...
摘要:其他的項(xiàng)目使用了拼裝樣式驗(yàn)證傳入的屬性是否是函數(shù)驗(yàn)證父組件傳入的數(shù)據(jù)格式是否正確五參考文獻(xiàn)談?wù)劦氖褂檬褂脠?chǎng)景 仿 taro-ui 實(shí)現(xiàn) modal 組件 小程序組件. 簡(jiǎn)介: 項(xiàng)目中使用到彈窗類的組件,重新制造了一個(gè)輪子. 源碼地址: https://github.com/xiangxiong... 編寫(xiě)完modal組件總計(jì)花了28分鐘. 效果圖: showImg(htt...
摘要:多端統(tǒng)一開(kāi)發(fā)框架優(yōu)秀學(xué)習(xí)資源匯總官方資源項(xiàng)目倉(cāng)庫(kù)官方文檔項(xiàng)目倉(cāng)庫(kù)官方文檔微信小程序官方文檔百度智能小程序官方文檔支付寶小程序官方文檔字節(jié)跳動(dòng)小程序官方文檔文章教程不敢閱讀包源碼帶你揭秘背后的哲學(xué)從到構(gòu)建適配不同端微信小程序等的應(yīng)用小程序最 Awesome Taro 多端統(tǒng)一開(kāi)發(fā)框架 Taro 優(yōu)秀學(xué)習(xí)資源匯總 showImg(https://segmentfault.com/img/r...
摘要:個(gè)人所有文章同步到前言最近公司準(zhǔn)備開(kāi)發(fā)幾款可以在微信小程序端和端同時(shí)運(yùn)行的一套商城,接著就是任務(wù)下發(fā)嘍,但是有一點(diǎn),時(shí)間緊任務(wù)重,直接說(shuō)其他的不管,反正幾個(gè)星期之內(nèi)必須上線,頭疼。 個(gè)人所有文章同步到:https://github.com/zhengzhuan... 前言 最近公司Boss準(zhǔn)備開(kāi)發(fā)幾款可以在微信小程序端和H5端同時(shí)運(yùn)行的一套商城,接著就是任務(wù)下發(fā)嘍,但是有一點(diǎn),時(shí)間緊任...
閱讀 2178·2021-11-24 09:38
閱讀 3242·2021-11-08 13:27
閱讀 3083·2021-09-10 10:51
閱讀 3143·2019-08-29 12:20
閱讀 663·2019-08-28 18:28
閱讀 3459·2019-08-26 11:53
閱讀 2706·2019-08-26 11:46
閱讀 1515·2019-08-26 10:56