摘要:作為兩個(gè)小程序開發(fā)框架都使用過,并應(yīng)用在生產(chǎn)環(huán)境里的人,自然是要比較一下兩者的異同點(diǎn)。在這里與當(dāng)前很流行的小程序開發(fā)框架之一進(jìn)行簡單對比,主要還是為了方便大家更快速地了解,從而選擇更適合自己的開發(fā)方式。
前言
前陣子,來自我們凹凸實(shí)驗(yàn)室的遵循 React 語法規(guī)范的多端開發(fā)方案 - Taro終于對外開源了,歡迎圍觀star(先打波廣告)。作為第一批使用了Taro開發(fā)的TOPLIFE小程序的開發(fā)人員之一,自然是走了不少彎路,躺了不少坑,也幫忙找過不少bug。現(xiàn)在項(xiàng)目總算是上線了,那么,也是時(shí)候給大家總結(jié)分享下了。
與wepy比較當(dāng)初開發(fā)TOPLIFE第一期的時(shí)候,用的其實(shí)是wepy(那時(shí)Taro還沒有開發(fā)完成),然后在第二期才全面轉(zhuǎn)換為用Taro開發(fā)。作為兩個(gè)小程序開發(fā)框架都使用過,并應(yīng)用在生產(chǎn)環(huán)境里的人,自然是要比較一下兩者的異同點(diǎn)。
相同點(diǎn)組件化開發(fā)
npm包支持
ES6+特性支持,Promise,Async Functions等
CSS預(yù)編譯器支持,Sass/Stylus/PostCSS等
支持使用Redux進(jìn)行狀態(tài)管理
…..
相同的地方也不用多說什么,都2018年了,這些特性的支持都是為了讓小程序開發(fā)變得更現(xiàn)代,更工程化,重點(diǎn)是區(qū)別之處
不同點(diǎn)開發(fā)風(fēng)格
實(shí)現(xiàn)原理
wepy支持slot,taro暫不支持直接渲染children
開發(fā)風(fēng)格
最大的不同之處,自然就是開發(fā)風(fēng)格上的差異,wepy使用的是類Vue開發(fā)風(fēng)格, Taro使用的是類React開發(fā)風(fēng)格,可以說開發(fā)體驗(yàn)上還是會(huì)有較大的區(qū)別。貼一下官方的demo簡單闡述下
wepy demo
view(class="container") view(class="userinfo" @tap="tap") mycom(:prop.sync="myprop" @fn.user="myevent") text {{now}}
taro demo
import Taro, { Component } from "@tarojs/taro" import { View, Button } from "@tarojs/components" export default class Index extends Component { constructor () { super(...arguments) this.state = { title: "首頁", list: [1, 2, 3] } } componentWillMount () {} componentDidMount () {} componentWillUpdate (nextProps, nextState) {} componentDidUpdate (prevProps, prevState) {} shouldComponentUpdate (nextProps, nextState) { return true } add = (e) => { // dosth } render () { return () } } {this.state.title} {this.state.list.map(item => { return ( {item} ) })}
可以見到在wepy里,css、template、script都放在一個(gè)wepy文件里,template還支持多種模板引擎語法,然后支持computed、watcher等屬性,這些都是典型的vue風(fēng)格
而在taro里,就是徹頭徹尾的react風(fēng)格,包括constructor,componentWillMount、componentDidMount等各種react的生命周期函數(shù),還有return里返回的jsx,熟悉react的人上手起來可以說是非常快了
除此之外還有一些細(xì)微的差異之處:
wepy里的模板,或者說是wxml,用的都是小程序里原生的組件,就是小程序文檔里的各種組件;而taro里使用的每個(gè)組件,都需要從@tarojs/components里引入,包括View,Text等基礎(chǔ)組件(這種做其實(shí)是為了轉(zhuǎn)換多端做準(zhǔn)備)
事件處理上
taro中,是用click事件代替tap事件
wepy使用的是簡寫的寫法@+事件;而taro則是on+事件名稱
阻止冒泡上wepy用的是@+事件.stop;而taro則是要顯式地使用e.stopPropagation()來阻止冒泡
事件傳參wepy可以直接在函數(shù)后面?zhèn)鲄ⅲ?b>@tap="click({{index}})";而taro則是使用bind傳參,如onClick={this.handleClick.bind(null, params)}
wepy使用的是小程序原生的生命周期,并且組件有page和component的區(qū)分;taro則是自己實(shí)現(xiàn)了類似react的生命周期,而且沒有page和component的區(qū)分,都是component
總的來說,畢竟是兩種不同的開發(fā)風(fēng)格,自然還是會(huì)有許多大大小小的差異。在這里與當(dāng)前很流行的小程序開發(fā)框架之一wepy進(jìn)行簡單對比,主要還是為了方便大家更快速地了解taro,從而選擇更適合自己的開發(fā)方式。
實(shí)踐體驗(yàn)taro官方提供的demo是很簡單的,主要是為了讓大家快速上手,入門。那么,當(dāng)我們要開發(fā)偏大型的項(xiàng)目時(shí),應(yīng)該如何使用taro使得開發(fā)體驗(yàn)更好,開發(fā)效率更高?作為深度參與TOPLIFE小程序開發(fā)的人員之一,談一談我的一些實(shí)踐體驗(yàn)及心得
如何組織代碼使用taro-cli生成模板是這樣的
├── dist 編譯結(jié)果目錄 ├── config 配置目錄 | ├── dev.js 開發(fā)時(shí)配置 | ├── index.js 默認(rèn)配置 | └── prod.js 打包時(shí)配置 ├── src 源碼目錄 | ├── pages 頁面文件目錄 | | ├── index index頁面目錄 | | | ├── index.js index頁面邏輯 | | | └── index.css index頁面樣式 | ├── app.css 項(xiàng)目總通用樣式 | └── app.js 項(xiàng)目入口文件 └── package.json
假如引入了redux,例如我們的項(xiàng)目,目錄是這樣的
├── dist 編譯結(jié)果目錄 ├── config 配置目錄 | ├── dev.js 開發(fā)時(shí)配置 | ├── index.js 默認(rèn)配置 | └── prod.js 打包時(shí)配置 ├── src 源碼目錄 | ├── actions redux里的actions | ├── asset 圖片等靜態(tài)資源 | ├── components 組件文件目錄 | ├── constants 存放常量的地方,例如api、一些配置項(xiàng) | ├── reducers redux里的reducers | ├── store redux里的store | ├── utils 存放工具類函數(shù) | ├── pages 頁面文件目錄 | | ├── index index頁面目錄 | | | ├── index.js index頁面邏輯 | | | └── index.css index頁面樣式 | ├── app.css 項(xiàng)目總通用樣式 | └── app.js 項(xiàng)目入口文件 └── package.json
比較常見的一種項(xiàng)目目錄組織方式,相比初始模板多了幾個(gè)文件夾,用于存放redux相關(guān)的內(nèi)容及其他的一些東西,整個(gè)項(xiàng)目結(jié)構(gòu)相信還是比較直觀,簡單明了的
更好地使用reduxredux大家應(yīng)該都不陌生,一種狀態(tài)管理的庫,通常會(huì)搭配一些中間件使用。我們的項(xiàng)目主要是用了redux-thunk和redux-logger中間件,一個(gè)用于處理異步請求,一個(gè)用于調(diào)試,追蹤actions
相信大家都遇到過這種時(shí)候,接口返回的數(shù)據(jù)和頁面顯示的數(shù)據(jù)并不是完全對應(yīng)的,往往需要再做一層預(yù)處理。那么這個(gè)業(yè)務(wù)邏輯應(yīng)該在哪里管理,是組件內(nèi)部,還是redux的流程里?
舉個(gè)例子:
例如上圖的購物車模塊,接口返回的數(shù)據(jù)是
{ code: 0, data: { shopMap: {...}, // 存放購物車?yán)锷唐返牡赇佇畔⒌膍ap goods: {...}, // 購物車?yán)锏纳唐沸畔? ... } ... }
對的,購車?yán)锏纳唐返赇伜蜕唐肥欠旁趦蓚€(gè)對象里面的,但視圖要求它們要顯示在一起。這時(shí)候,如果直接將返回的數(shù)據(jù)存到store,然后在組件內(nèi)部render的時(shí)候東拼西湊,將兩者信息匹配,再做顯示的話,會(huì)顯得組件內(nèi)部的邏輯十分的混亂,不夠純粹。
所以,我個(gè)人比較推薦的做法是,在接口返回?cái)?shù)據(jù)之后,直接將其處理為與頁面顯示對應(yīng)的數(shù)據(jù),然后再dispatch處理后的數(shù)據(jù),相當(dāng)于做了一層攔截,像下面這樣:
const data = result.data // result為接口返回的數(shù)據(jù) const cartData = handleCartData(data) // handleCartData為處理數(shù)據(jù)的函數(shù) dispatch({type: "RECEIVE_CART", payload: cartData}) // dispatch處理過后的函數(shù) ... // handleCartData處理后的數(shù)據(jù) { commoditys: [{ shop: {...}, // 商品店鋪的信息 goods: {...}, // 對應(yīng)商品信息 }, ...] }
可以見到,處理數(shù)據(jù)的流程在render前被攔截處理了,將對應(yīng)的商品店鋪和商品放在了一個(gè)對象了.
這樣做有幾個(gè)好處
一個(gè)是組件的渲染更純粹,在組件內(nèi)部不用再關(guān)心如何將數(shù)據(jù)修修改改而滿足視圖要求,只需關(guān)心組件本身的邏輯,例如點(diǎn)擊事件,用戶交互等
二是數(shù)據(jù)的流動(dòng)更可控,假如后續(xù)后臺返回的數(shù)據(jù)有變動(dòng),我們要做的只是改變handleCartData函數(shù)里面的邏輯,不用改動(dòng)組件內(nèi)部的邏輯。
后臺數(shù)據(jù)——>攔截處理——>期望的數(shù)據(jù)結(jié)構(gòu)——>組件
實(shí)際上,不只是后臺數(shù)據(jù)返回的時(shí)候,其它數(shù)據(jù)結(jié)構(gòu)需要變動(dòng)的時(shí)候都可以做一層數(shù)據(jù)攔截,攔截的時(shí)機(jī)也可以根據(jù)業(yè)務(wù)邏輯調(diào)整,重點(diǎn)是要讓組件內(nèi)部本身不關(guān)心數(shù)據(jù)與視圖是否對應(yīng),只專注于內(nèi)部交互的邏輯,這也很符合react本身的初衷,數(shù)據(jù)驅(qū)動(dòng)視圖
connect大家都知道是用來連接store、actions和組件的,很多時(shí)候就只是根據(jù)樣板代碼復(fù)制一下,改改組件各自的store、actions。實(shí)際上,我們還可以做一些別的處理,例如:
export default connect(({ cart, }) => ({ couponData: cart.couponData, commoditys: cart.commoditys, editSkuData: cart.editSkuData }), (dispatch) => ({ // ...actions綁定 }))(Cart) // 組件里 render () { const isShowCoupon = this.props.couponData.length !== 0 return isShowCoupon &&}
上面是很普通的一種connect寫法,然后render函數(shù)根據(jù)couponData里是否數(shù)據(jù)來渲染。這時(shí)候,我們可以把this.props.couponData.length !== 0這個(gè)判斷丟到connect里,達(dá)成一種computed的效果,如下:
export default connect(({ cart, }) => { const { couponData, commoditys, editSkuData } = cart const isShowCoupon = couponData.length !== 0 return { isShowCoupon, couponData, commoditys, editSkuData }}, (dispatch) => ({ // ...actions綁定 }))(Cart) // 組件里 render () { return this.props.isShowCoupon &&}
可以見到,在connect里定義了isShowCoupon變量,實(shí)現(xiàn)了根據(jù)couponData來進(jìn)行computed的效果
實(shí)際上,這也是一種數(shù)據(jù)攔截處理。除了computed,還可以實(shí)現(xiàn)其它的功能,具體就由各位看官自由發(fā)揮了
一些需要注意的地方那taro,或者是小程序開發(fā),有沒有什么要注意的地方?當(dāng)然有,走過的彎路可以說是非常多了
估計(jì)是每個(gè)頁面的數(shù)據(jù)在小程序內(nèi)部都有緩存,所以做了10層的限制。帶來的問題就是假如頁面存在循環(huán)跳轉(zhuǎn),即A頁面可以跳到B頁面,B頁面也可以跳到A頁面,然后用戶從A進(jìn)入了B,想返回A的時(shí)候,往往是直接在B頁面里點(diǎn)擊跳轉(zhuǎn)到A,而不是點(diǎn)返回回到A,如此一來,10層很快就突破了。所以我們自己對navigateTo函數(shù)做了一層封裝,防止溢出
上面說到,頁面內(nèi)容有緩存。所以假如某個(gè)頁面是根據(jù)不同的數(shù)據(jù)渲染視圖,新渲染時(shí)會(huì)有上一次渲染的緩存,導(dǎo)致頁面看起來有個(gè)閃爍的變化,用戶體驗(yàn)非常不好。其實(shí)解決的辦法也很簡單,每次在componentWillUnmount生命周期中清理一下當(dāng)前頁面的數(shù)據(jù)就好了。小程序說到底不是h5,不會(huì)說每次進(jìn)入頁面就會(huì)刷新,也不會(huì)離開就銷毀,刷新,清理數(shù)據(jù)的動(dòng)作都需要自己再生命周期函數(shù)里主動(dòng)觸發(fā)
頁面的滾動(dòng)事件只能通過onPageScroll來監(jiān)聽,所以當(dāng)我想在組件里進(jìn)監(jiān)聽操作時(shí),要將該部分的邏輯提前到onPageScroll函數(shù),提高了抽象成本。例如我需要開發(fā)一個(gè)滾動(dòng)到某個(gè)位置就吸頂?shù)?b>tab,本來可以在tab內(nèi)部處理的邏輯被提前了,減少了其可復(fù)用性
本來也想詳細(xì)描述下的,不過在我們幾位大佬的努力,加班加點(diǎn)下,已經(jīng)開發(fā)出eslint插件,及補(bǔ)充完整了taro文檔。大家只要遵循eslint插件規(guī)范,查看文檔,應(yīng)該不會(huì)有太大問題,有問題歡迎提issue
總結(jié)總的來說,用taro來開發(fā)小程序體驗(yàn)還是很不錯(cuò)的,最重要的是,可以使用jsx寫小程序了!?。∽鳛閞eact粉的一員,可以說是相當(dāng)?shù)呐d奮了~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/95813.html
摘要:多端統(tǒng)一開發(fā)框架優(yōu)秀學(xué)習(xí)資源匯總官方資源項(xiàng)目倉庫官方文檔項(xiàng)目倉庫官方文檔微信小程序官方文檔百度智能小程序官方文檔支付寶小程序官方文檔字節(jié)跳動(dòng)小程序官方文檔文章教程不敢閱讀包源碼帶你揭秘背后的哲學(xué)從到構(gòu)建適配不同端微信小程序等的應(yīng)用小程序最 Awesome Taro 多端統(tǒng)一開發(fā)框架 Taro 優(yōu)秀學(xué)習(xí)資源匯總 showImg(https://segmentfault.com/img/r...
摘要:所以在小程序出現(xiàn)之后,一股框架之風(fēng)也很快的出現(xiàn),微信小程序剛推出之后,就出現(xiàn)了兩個(gè)比較出名的小程序開發(fā)框架,。 原文地址:https://ant-move.github.io/we... 這里說的去除小程序框架其實(shí)并不嚴(yán)謹(jǐn),因?yàn)樾〕绦虮旧硪菜闶且粋€(gè)框架,而且是一個(gè)功能更加完善的框架系統(tǒng)。在前端的概念中,我們一般說一個(gè)框架是指一個(gè)用來幫助開發(fā)者構(gòu)建用戶界面的框架,而小程序框架本身不僅僅包...
摘要:整個(gè)小程序所有分包大小不超過單個(gè)分包主包大小不能超過微信小程序主流框架對比應(yīng)該算是最早發(fā)布的小程序開發(fā)框架,提供了類的語法風(fēng)格和特性,現(xiàn)階段應(yīng)該也是應(yīng)用最廣泛的框架吧。不過微信官方為了防止下載離線包的時(shí)間過程,也嚴(yán)格限制了小程序包的體積。 那些年我們踩過的坑css樣式不能引用本地圖片資源,只能引用線上資源(background-image),引用本地圖片資源只能用標(biāo)簽。{{}}不能執(zhí)行...
摘要:前言是一個(gè)可以很好實(shí)現(xiàn)一次開發(fā),多端統(tǒng)一的框架,本文只介紹它小程序端開發(fā)的一些內(nèi)容。 前言:taro是一個(gè)可以很好實(shí)現(xiàn)一次開發(fā),多端統(tǒng)一的框架,本文只介紹它小程序端開發(fā)的一些內(nèi)容。小程序項(xiàng)目搭建gitup已經(jīng)有很清楚的說明:https://github.com/NervJS/taro 一.主要操作步驟及命令: 1.cnpm install -g @tarojs/cli 全局安裝taro...
閱讀 1308·2021-09-04 16:41
閱讀 2524·2021-09-02 10:18
閱讀 983·2019-08-29 16:40
閱讀 2676·2019-08-29 16:14
閱讀 1024·2019-08-26 13:41
閱讀 1357·2019-08-26 12:24
閱讀 794·2019-08-26 10:24
閱讀 2933·2019-08-23 17:54