保姆级!!前端必会Taro入门级教学!!
我是歌謠 放棄很容易 但是堅持一定很酷 微信公眾號關注前端小歌謠獲取前端知識
本文將介紹 Taro 是如何從一個為了解決小程序開發問題的框架演變成一個多端統一開發框架的。
使用 React 語法來寫小程序
談一談小程序開發
微信小程序為我們的業務提供了一種新的展現形態,但對于開發者來說,開發體驗則顯得并不那么友好。
首先,從文件組織上看,一個小程序頁面或組件,需要同時包含 4 個文件:腳本邏輯、樣式、模板以及配置文件,在開發一個功能模塊時,就需要在 4 個文件之間切換,而當功能模塊多的話,就需要在多個文件之間切換,這樣顯然非常浪費時間。
其次,從開發方式上看,在前端工程化思想深入人心的今天,小程序的種種開發方式顯得有些落后了,主要體現在以下幾個方面:
- 沒有自定義文件預處理,無法直接使用 Sass、Less 以及較新的 ES.Next 語法;
- 字符串模板太過孱弱,小程序的字符串模板仿的是 Vue,但是沒有提供 Vue 那么多的語法糖,當實現一些比較復雜的處理時,寫起來就非常麻煩,雖然提供了 wxs 作為補充,但是使用體驗還是非常糟糕;
- 缺乏測試套件,無法編寫測試代碼來保證項目質量,也就不能進行持續集成,自動化打包。
所以,從開發方式上看,小程序開發沒有融入目前主流的工程化開發思想,很多業界開發模式與工具沒有在小程序開發中得到相應體現,像是從前端工業時代回退到了刀耕火種的年代。
最后,從代碼規范上看,小程序的規范有很多不統一的地方,例如內置組件的屬性名,有時候是全小寫,有時候是 CamelCase 格式,有時候又是中劃線分割的形式,這樣就導致編碼的時候得不時查閱文檔才能確定寫法。
如何更優雅地開發小程序
在 Taro 的設計之初,我們的想法就是希望能夠以一種更加優雅的方式來開發小程序,解決小程序開發上的種種痛點,首先我們希望能使用前端工程化的方式來進行開發,同時在語法上,我們希望能拋棄小程序的四不像語法,遵循一套我們熟悉的框架語法來進行開發,這樣不僅能更好地保證開發質量、提升開發體驗,同時也能大大降低開發者開發小程序的成本。
于是,在開發方式上,Taro 打造了一套完善編譯工具,引入了前置編譯的機制,可以自動化地對源文件進行一系列的處理,最終輸出小程序上的可執行文件,包括代碼的編譯轉換處理,加入文件預處理功能,支持 NPM 包管理等等,這一部分的原理,將會在后續章節中為大家介紹。而語法標準上,我們把目光投向了市面上流行的三大前端框架。
React、Vue、Angular 是目前前端框架三巨頭,他們各有各的風格,關于他們的優劣,在業界也是一直爭論不休,這本身也是智者見智仁者見仁的事,所以在本文中就不再評述。Taro 最終采用的是 React 語法來作為自己的語法標準,主要有以下幾點考慮:
- React 是一個非常流行的框架,也有廣大的受眾,使用它也能降低小程序開發的學習成本;
- 小程序的數據驅動模板更新的思想與實現機制,與 React 類似;
- React 采用 JSX 作為自身模板,JSX 相比字符串模板來說更自由,更自然,更具表現力,不需要依賴字符串模板的各種語法糖,也能完成復雜的處理
- React 本身有跨端的實現方案 - React Native,并且非常成熟,社區活躍,對于 Taro 來說有更多的多端開發可能性。
最終,Taro 采用了 React 語法來作為自己的語法標準,配合前端工程化的思想,為小程序開發打造了更加優雅的開發體驗。
如何實現優雅
那么如何實現使用 React 來開發小程序呢?在 Taro 中采用的是編譯原理的思想,所謂編譯原理,就是一個對輸入的源代碼進行語法分析,語法樹構建,隨后對語法樹進行轉換操作再解析生成目標代碼的過程。
探索多端可能性
多端統一開發一直是所有開發人員的共同追求。在終端碎片化的大背景下,前有 Hybrid 模式拉開序幕,后有 React Native、Weex 風起云涌,再到如今 Flutter 橫空出世,種種這些都是為了能夠 Write once, run anywhere 。給每一種終端單獨進行開發的成本是昂貴的,所以一個能夠盡可能抹平多端開發差異的開發解決方案就顯得極為重要。
多端轉換原理
開發時我們遵循 React 語法標準,結合編譯原理的思想,對代碼文件進行一系列轉換操作,最終獲得可以在小程序運行的代碼。而 React 最開始就是為了解決 Web 開發而生的,所以對代碼稍加改動,也可以直接生成在 Web 端運行的代碼,而同屬 React 語法體系下的 React Native,也能夠很便捷地提供支持。同理其他平臺,如快應用、百度小程序等,將源碼進行編譯轉換操作,也能獲得該平臺下的對應語法代碼。
?
抹平多端差異
基于編譯原理,我們已經可以將 Taro 源碼編譯成不同端上可以運行的代碼了,但是這對于實現多端開發還是遠遠不夠。因為不同的平臺都有自己的特性,每一個平臺都不盡相同,這些差異主要體現在不同的組件標準與不同的 API 標準以及不同的運行機制上。
?
可以看出小程序和 Web 端上組件標準與 API 標準有很大差異,這些差異僅僅通過代碼編譯手段是無法抹平的,例如你不能直接在編譯時將小程序的 ?直接編譯成
這一套標準主要以三個部分組成,包括標準運行時框架、標準基礎組件庫、標準端能力 API,其中運行時框架和 API 對應 @taro/taro,組件庫對應 @tarojs/components,通過在不同端實現這些標準,從而達到去差異化的目的。
而在標準的定制上,起初我們想重新定制一套標準規范,但是發現在所有端都得實現這套標準的成本太高,所以我們就思考為什么不以一個端的組件庫、API 為標準呢?這樣不僅省去了標準定制的時間,而且在這個端上我們可以不用去實現這套標準了。最終在所有端中,我們挑選了微信小程序的組件庫和 API 來作為 Taro 的運行時標準,因為微信小程序的文檔非常完善,而且組件與 API 也是非常豐富,同時最重要的是,百度小程序以及支付寶小程序都是遵循的微信小程序的標準,這樣一來,Taro 在實現這兩個平臺的轉換上成本就大大降低了。?
?
運行時
本文介紹的是 Taro 在編譯成小程序和 H5 運行時發生了什么
JSX 轉換微信小程序模板的實現
以這段代碼為例:
import Taro, { Component } from '@tarojs/taro' import { View, Text } from '@tarojs/components'class Home extends Component {config = {navigationBarTitleText: '首頁'}state = {numbers: [1, 2, 3, 4, 5]}handleClick = () => {this.props.onTest()}render () {const oddNumbers = this.state.numbers.filter(number => number & 2)return (<ScrollView className='home' scrollTop={false}>奇數:{oddNumbers.map(number => <Text onClick={this.handleClick}>{number}</Text>)}偶數:{numbers.map(number => number % 2 === 0 && <Text onClick={this.handleClick}>{number}</Text>)}</ScrollView>)} }Taro 的結構主要分兩個方面:運行時和編譯時。運行時負責把編譯后到代碼運行在本不能運行的對應環境中,你可以把 Taro 運行時理解為前端開發當中 polyfill。舉例來說,小程序新建一個頁面是使用 Page 方法傳入一個字面量對象,并不支持使用類。如果全部依賴編譯時的話,那么我們要做到事情大概就是把類轉化成對象,把 state 變為 data,把生命周期例如 componentDidMount 轉化成 onReady,把事件由可能的類函數(Class method)和類屬性函數(Class property function) 轉化成字面量對象方法(Object property function)等等。
但這顯然會讓我們的編譯時工作變得非常繁重,在一個類異常復雜時出錯的概率也會變高。但我們有更好的辦法:實現一個 createPage 方法,接受一個類作為參數,返回一個小程序 Page 方法所需要的字面量對象。這樣不僅簡化了編譯時的工作,我們還可以在 createPage 對編譯時產出的類做各種操作和優化。通過運行時把工作分離了之后,再編譯時我們只需要在文件底部加上一行代碼 Page(createPage(componentName)) 即可。
如果你是從 Taro CLI 的 dist 文件夾看編譯后的代碼會發現它相當復雜,那是因為代碼會再經過 babel 編譯為 ES5。
除了 Page 類型之外,小程序還有 Component 類型,所以 Taro 其實還有 createComponent 方法。由于 Component 在小程序里是全局變量,因此我們還得把 import { Component } from '@tarojs/taro' 的 Component 重命名。
回到一開始那段代碼,我們定義了一個類屬性 config,config 是一個對象表達式(Object Expression),這個對象表達式只接受鍵值為標識符(Identifier)或字符串,而鍵名只能是基本類型。這樣簡單的情況我們只需要把這個對象表達式轉換為 JSON 即可。另外一個類屬性 state 在 Page 當中有點像是小程序的 data,但它在多數情況不是完整的 data(下文會繼續討論data)。這里我們不用做過多的操作,babel的插件 transform-class-proerties 會把它編譯到類的構造器中。函數 handleClick 我們交給運行時處理,有興趣的同學可以跳到 Taro 運行時原理查看具體技術細節。
再來看我們的 render() 函數,它的第一行代碼通過 filter 把數字數組的所有偶數項都過濾掉,真正用來循環的是 oddNumbers,而 oddNumbers 并沒有在 this.state 中,所以我們必須手動把它加入到 this.state。和 React 一樣,Taro 每次更新都會調用 render 函數,但和 React 不同的是,React 的 render 是一個創建虛擬 DOM 的方法,而 Taro 的 render 會被重命名為 _createData,它是一個創建數據的方法:在 JSX 使用過的數據都在這里被創建最后放到小程序 Page 或 Component 工廠方法中的 data 。最終我們的 render 方法會被編譯為:
_createData() {this.__state = arguments[0] || this.state || {};this.__props = arguments[1] || this.props || {};const oddNumbers = this.__state.numbers.filter(number => number & 2);Object.assign(this.__state, {oddNumbers: oddNumbers});return this.__state; }開發指導
我是歌謠 放棄很容易 但是堅持一定很酷
?
總結
以上是生活随笔為你收集整理的保姆级!!前端必会Taro入门级教学!!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java宿舍管理系统代码_JAVA学生宿
- 下一篇: Excel VBA函数和过程调用方法总结