网友真实露脸自拍10p,成人国产精品秘?久久久按摩,国产精品久久久久久无码不卡,成人免费区一区二区三区

小程序模板網

JDReact 小程序雙向轉換工具介紹

發布時間:2018-07-17 08:48 所屬欄目:小程序開發教程

嚴康

資深前端工程師,負責JDReact框架前端及小程序轉換引擎開發

CMO體系-商城前臺產品研發部-基礎平臺研發部-技術平臺綜合組-多端融合平臺組

臧國東

前端工程師,負責JDReact框架前端及小程序轉換引擎開發

CMO體系-商城前臺產品研發部-基礎平臺研發部-技術平臺綜合組-多端融合平臺組

概述

JDReact是CMO體系商城前臺產品研發部推出的多端融合開發框架。經過不斷的技術完善,目前已經在手機京東客戶端累計接入 100+ 業務,穩定支撐 千萬 級DAU,并對外支持 15+ 個獨立APP,擁有完善的 API 和功能強大的開發 IDE 工具。

本文重點介紹了JDReact提供的小程序雙向轉換工具的原理及用法,通過此工具可以把已經開發的微信小程序低成本轉換成JDReact應用,也支持把現有JDReact業務低成本轉換成微信小程序應用,完全實現了JDReact和微信小程序生態的打通。

背景

此項目的最初靈感來源于我們團隊今年5月份參加第六屆黑客馬拉松大賽并獲得冠軍的項目“微信小程序一鍵轉換工具” http://tech.jd.com/techical/questionDetail?id=771 (京東內網)

因為我們在進行項目開發時,常常會遇到以下情況:

01

場景一:已經開發微信小程序,遷移到APP

項目之初,為了更好的利用微信的流量,更加方便的推廣,我們會先直接發布一個小程序,等到后來我們的用戶越來越多,應用也變得越來越復雜。這個時候想要把這個應用獨立出來,把客戶掌握在自己手里,進一步定制應用。此時,沒有其他辦法,我們只能叫上Android,IOS開發人員,叫上之前的產品經理,之前的測試把之前小程序的功能再重新在原生上實現一遍。

02

場景二:已經開發APP,遷移至小程序生態

也可能,我們現在已經有了獨立App,現在由于種種原因(流量的需求,運營的需要),需要發布一個小程序的版本。怎么辦呢?同樣我們只能叫上小程序開發人員,之前的產品經理,之前的測試在復制一個小程序的版本。

03

場景三:新業務開發,技術選型中

或者,我們現在即將開始一個新的項目,這個項目既有獨立App也有小程序版本(或者可見的未來會有兩個版本)。 那么我們是不是需要保持原生團隊, 小程序團隊,從而進行兩個版本的開發呢?

如果我們可以把JDReact的應用轉化為小程序,把小程序轉化為JDReact應用,那么我們就可以低成本的把原來的JDReact項目/小程序項目移植到另一端了。而且新開始的項目我們就可以根據人員配置只開發一個JDReact的版本或者小程序的版本,等未來需要的時候,直接轉化為對應的另一端。

由于只需要維護一端的版本,就可以大大的降低軟件工程師的工作,同時產品,測試的工作量也會相應的減輕很多。另外, 我們希望轉化之后的代碼具有良好的可讀性, 方便再次開發與修改。

效果演示

我們先用一個實際的例子來展示下轉化工具的效果, 我們利用JDReact轉換工具將  “值得買京東優選”的微信小程序 轉化為對應的 JDReact版本 并運行在 手機京東客戶端中 ;

首先看一下微信小程序版“值得買京東優選”

轉化引擎將會遍歷尋找小程序源代碼目錄中的wxml,進行轉化期間會合并其對應的wxss, json, js文件。

轉化完成之后,啟動生成的JDReact原代碼目錄,運行模擬器查看效果。

以下是運行中手機京東客戶端中的JDReact版“值得買京東優選”

原理介紹

不管是React應用還是小程序應用都可以表達為:ui = f(data)。并且他們提供很相似的數據更新方式,小程序是 setData(newData, cb) , React是  setState(newState,cb) ,這兩個基本條件是我們轉化引擎的前提,基于此前提,轉化工作理論上是可行的。

f在React里面可以簡單的理解為JSX,在小程序里面可以理解為wxml。wxml是小程序提供的“靜態”的書寫ui的方式靈活性比較低。JSX是react提供的方式,很靈活,里面可以嵌入任何表達式,本質上就是JS。如果我們可以把JSX代碼翻譯為等效的wxml代碼,把wxml代碼翻譯為等效的JSX代碼,那么我們就有能力實現兩種應用的轉化。

顯然,我們的引擎必須能夠“讀懂”代碼,為了實現這個目標,首先我們將代碼轉化為AST格式,然后根據相應規則不斷的修改AST結構,最后生成新的代碼。通過babel-parse(把源代碼解析為AST),babel-traverse(遍歷操作AST),babel-generator(生成新代碼)來實現對源代碼的操作。這個相應規則源自于兩端的等效寫法。 比如說: wx:for 和 Array.map的對應, wx:if和邏輯表達式的對應。

然而,并不是所有的規則都這么顯而易見

比如JSX

對于這種情況我們會不斷遍歷JSX表達式,如果發現是函數調用,將會用“返回值替換”, 也就是會用getView的返回值來替換對應JSX表達式,替換的時候需要處理好數據綁定。

再比如下的JSX

wxml的變量綁定“{{}}”是不能出現函數調用(wxs除外)的,這種情況,我們將會使用“表達式前置”, 也就是相應表達式的值提前放置在小程序的data中,轉化之后的wxml可能如下:

遍歷AST的時候,需要不斷的判斷 JSX表達式 是否需要前置。最后轉化之后的data會保護很多這樣的var

由于JSX的足夠靈活,在進行JSX轉向wxml,我們將會有很多類似的轉化規則。

那是不是 wxml轉JSX就一帆風順呢? 也不是, 首先一個問題。babel-parse并不識別wxml代碼格式。對于wxml,我們需要預處理wxml, 使其可以被parse識別。另外wxml的很多奇怪表現也是我們轉化的時候需要兼容的。

比如:

小程序 的data里面并沒有a屬性,更別說b屬性,c屬性。但是這個在小程序里面是表現正常的,而且很常見。我們不希望轉化之后的程序在這種情況下報錯,我們對這種表達式進行了容錯,react-native(預計0.56版本)支持optional-chaining之后,我們也會跟進用optional-chaining來改造這種情況。

wxml到JSX的轉化,我們已經基本完成。JSX到wxml的轉化已經覆蓋所有常見的寫法。 隨著越來越多的規則被添加進來,我們轉化引擎能夠覆蓋的情況將會越來越多。

對齊兩端組件

wxml與JSX的雙向轉化成功,是轉化引擎的第一步。

但是轉化引擎應用于實際項目還有一段距離,因為不管是小程序項目還是JDReact項目都不可能只有View, Text組件, 即使我們把 users && <FlatList/>  轉化為小程序  <FlatList wx:if="{{users}}"/> 也是沒有作用的,小程序根本就不認識FlatList。 要想讓小程序認識FlatList,我們需要在小程序端實現一個小程序版的FlatList,好在發展到今天,小程序的自定義組件已經很完善。

意味著我們需要對齊兩端組件,需要在小程序端實現一套JDReact的組件庫,包括FlatList, SectionList,JDImage,JDSwiper等,同時實現組件的對應屬性。 在React Native端,我們也必不可少的需要實現一套這樣的小程序組件,包括 form,radio, radio-groupd等。實際上出于對齊屬性的考慮,包括view/View, text/Text這些基本組件,也是通過在另外一端實現對應組件這種方式實現的。

對齊小程序組件庫:

對齊React Native 和 JDReact組件庫:

生命周期和事件

data驅動視圖, 生命周期和事件提供了對data修改的時機。小程序的組件提供了與React相似的生命周期

小程序自定義組件生命周期: 

React的生命周期:

對于兩端意義相同的生命周期,比如ready和componentDidMount,會在遍歷AST的時候進行修改,對于那些React存在,小程序不存在的生命周期我們會在小程序調用setData前后進行模擬。

另外,小程序的Page具有和組件不一樣的生命周期,其中有些比如 onShow,onHide需要和導航器配合實現。

小程序的事件系統源自于web,而RN是自己有一套獨立的手勢系統,這兩種有一定差異。 明顯的,小程序的每一個組件都可以響應事件,而RN的組件一般只是Touchable** 系列的組件響應事件。

對于這種情況,我們會檢測每一個小程序組件,一旦發現組件響應了事件,就給對應的RN組件加上手勢系統, 另外一個比較大的差異,RN的事件是不冒泡的。 除了這些差異, 兩邊的事件基本是可以對應上的,比如bindtap對應onPress。處理方式和生命周期大同小異。

如果說React Native轉化為小程序難點是要處理JSX的靈活,那么小程序項目轉化為React Native的坑就是樣式了。小程序的wxss源自于css,基本上是css的全集。而React Native采用Yoga作為樣式布局系統,Yoga是基于C實現的一套Flexbox布局系統。

所以,在進行小程序樣式轉化時,原有的小程序wxss代碼必須進行適配才可以接入到RN項目中,產生效果,適配過程主要需要解決下面幾個問題。

1. RN不支持CSS選擇器

在 React Native中為一個元素指定某種樣式,只可采用如下方式:

在React Native中,只可以通過為某元素明確style來賦予樣式,在小程序以及web中,樣式賦予則非常的靈活,作為一個簡單的例子,

此時只需要在對應的css文件中寫 入

在這個例子中,我們用到了css提供的元素選擇器(div),類選擇器(.a)。css提供了數十種選擇器,功能十分強大。然而RN中卻沒有支持任何一種選擇器,因此在進行小程序樣式轉化前,首先要考慮如何適配小程序的css的選擇器功能。

css提供了數十種選擇器,且各類選擇器間的組合非常靈活,而究其根本,其最基本元素僅有五種

其余類似于后代選擇器之類則可以看作連接符,例如對 于

因此大多數的CSS組合可以看作 [基本元素,連接符,基本元素…] 的形式,考慮到這一點后,我們進一步研究發現,其實所有基本類型選擇器都可以由某個標簽的標簽名,以及prop屬性來獲取,而所有連接符關系,都可以通過元素在小程序wxml文件中的文檔結構來進行計算匹配,我們通過抽象語法樹的方式解析wxml文件,為每個元素注入了它自身在文檔結構中的信息,來進行選擇器的計算適配,目前已經提供了近10種最常用的選擇器類型,且功能在不斷的完善與擴展。

2. CSS寫法的不一致

RN與小程序對于CSS中的寫法差異較大。選擇器方面,小程序CSS中選擇器名可以為相對隨意的字符串,例如’test-a¥b’也是有效的選擇器名,而在RN中,這并不是一個有效的變量命名,因此我們在RN中,我們將所有的選擇器名定位字符串類型,例如上述選擇器名將轉為

因此可以完整適配小程序中任意的命名方式。

另一方面,在屬性上存在寫法不一致的情形。例如,小程序中寫為border-width,而適配到RN中,則需要轉化為borderWidth,不僅如此,對于一些簡寫的屬性,例如小程序CSS中的

有著明確的語意,然而在RN中,無法解析這樣的語法,我們也對此進行了轉化,例如對于上述情形,我們在RN中解析并轉化為了

在RN中與小程序還有眾多寫法不一致的情形,對此我們盡最大可能提供了支持,并給出了規范。

3. 在RN與CSS中存在屬性默認值的不同

RN與小程序CSS存在很多屬性默認值的不同,這就導致了,即使選擇器適配功能完好,同樣的CSS代碼,在小程序上表現正常,RN上則顯示不正確。

比如,RN中采用flex布局,其flex方向默認為列布局,而在小程序CSS則默認為行布局。又如,RN中的flexShrink默認值為0,小程序CSS中則為1,這會導致頁面展示的不正常。

對此,我們提供了適配方案,首先我們會對小程序開發者提出一些基本要求,例如必須采用flex布局方式。另一方面,我們會對于每個RN中與小程序CSS中默認值存在差異的情況進行修正,盡可能讓小程序開發者不改變自己的CSS寫法。對于上述兩種情形,我們都會提供出具體的規范。

我們仔細研究了小程序CSS與RN中CSS的不同,并在最大程度上適配了小程序CSS的寫法,讓用戶可以自由使用小程序CSS的各項功能,這一切都是為了讓開發者獲得更好的開發體驗。

另外,為了提供更好的服務,我們制定了具體的規范,確保小程序開發者在現有規范下開發完成后,轉化前與轉化后頁面展示完全一致。

css轉化流程總結如下:

限制與約束

有的時候, 知道我們“做不到什么”更加重要。

由于AST只是靜態分析代碼,許多“運行時”才能夠得到的信息是得不到的,比如:

這種情況,我們根本不知道 a 到底是什么, “返回值替換” 就會出問題。

又比如:

這里的ForFun會直接導致我們判斷React組件失敗,代碼需要自律!

React中的高價組件暫時不支持轉換,并且我們目前只支持React Native官方組件和JDReact通過的組件。

兩邊系統的差異和限制,在小程序端,比如小程序的包大小要在2M以內, 那么當JDReact轉化過來的小程序打完包也必須在2M以內, 比如小程序的tab頁個數,路由深度也是有限制的,

另外,前文提到的,在小程序向React應用轉化的時候,對小程序本身所使用的樣式是有限制的。

在RN端,小程序的scroll-view是可以上下左右滾動的,而RN的只可以一個方向, 事件處理的差異等等。

對于所有的這些限制和約束,我們后續會給出一份完整的清單,同時也會給出相應的替換方案。

合作共贏

目前我們已經初步實現了反向轉換引擎,正向轉換引擎也正在加速開發中。非常歡迎有興趣的個人或團隊和我們交流合作,合作試用可以在公眾號下方留言ERP或聯系方式!!!



易優小程序(企業版)+靈活api+前后代碼開源 碼云倉庫:starfork
本文地址:http://www.xiuhaier.com/wxmini/doc/course/24633.html 復制鏈接 如需定制請聯系易優客服咨詢:800182392 點擊咨詢
QQ在線咨詢
AI智能客服 ×