JDReact 平台是在 Facebook ReactNative 开源框架基础上,进行了深度二次开发和功能扩展。不仅打通了 Android/iOS/Web 三端平台,而且对京东移动端基础业务能力进行了 SDK 级别的封装,提供了统一、易于开发的 API 。基于以上种种优势,加油卡壳牌业务决定使用 JDReact 技术进行开发。
由于这是我们团队首次使用 JDReact ,在开发过程中遇到了很多问题:不熟悉 JDReact 提供的 API 、如何调用后台数据接口?怎样切换测试、预发环境?开发完后怎样打包?如何上线?等等每个流程都不熟悉。因此,在完成项目之后,很想做一个总结,从前期准备到最终项目上线的整个流程做一个分享,希望能为初次使用 JDReact 的同事有所帮助!如有错误,还请多多指教!
1 前期准备
1.1 项目背景
加油卡壳牌业务是京东APP中的一个项目,可以从首页的「充值缴费」入口进去,如下视频演示:
1.2 项目环境配置
1.2.1 开发分支以及文件结构
初始项目中只包含一个 dev 分支,最后打包 APP 时会从该分支中抽取代码,所以我们新建了一个 trunk 分支,平时在该分支上进行开发,最后打包 APP 的时候再切换到 dev 分支,合并代码。
对于文件结构,如上图所示,其中 Navigation.js 设置页面路由信息,以及打开项目时进入的默认页面;pages 文件夹下存放项目的每个页面代码;images 存放项目开发中使用到的图片;components 文件夹下存放页面中用到的各个组件。
1.2.2 安装依赖环境
按照 JDReact 团队给出的安装依赖环境的步骤,当执行 npm start 命令之后,理想状态下会出现下面的提示:
很不幸的是,有时候会出现如下警告:
根据提示,可以看到打开 .babel.json 文件的时候出错,其实如果忽略这些警告,也可以打开京东 APP 进行调试的,但是如果想解决这个问题可以参考下面的步骤:
找到C:\Users\用户名.babel.json文件右击——属性——安全——SYSTEM的权限全部改为允许(如果已经改过权限,可以来回切换一下),重新执行 npm start 就可以了。
1.2.3 安装 React 语法高亮插件
项目是在 sublime 中开发的,但是在编写 JDReact 代码时,整个代码的高亮是混乱的,如下图所示:
因此,需要安装 Babel Snippets 插件来解决高亮问题,该插件可以使 React.js、JSX 语法代码高亮。安装方式:在 sublime 中,ctrl+shift+p 打开面板选择 Install Package ,输入 babel Snippets 点击安装,安装完毕后再次 ctrl+shift+p ,选择 set syntax JavaScript(babel) ,则 React 语法代码可以高亮,方便我们接下来的开发。执行完毕后效果如下图所示:
1.3 在无线持续构建平台打包项目
手机安装 debug 版本的京东 APP 之后,可以在手机端实时看到开发的代码效果,那么如何生成 APP 呢?因为构建平台会抽取项目中 dev 分支的代码,所以如果代码有所改动,先把 trunk 分支代码合并到 dev 分支。整体思路是把业务代码以插件形式打包进JDReact,然后再打包包含该插件的 APP 。打包流程如下:
对于 Android 版本,首先打开无线构建平台网址 ,选择一键打包—— JDReact,依次选择插件名称——平台选择(android)—— dev 分支——点击开始构建。
打包好JDReact后,再打包京东 APP:
选择京东商城—— android ——其中 debug 版本可以晃动手机进行调试,release 版本不可以调试,近似于真实环境,所以如果平时开发调试的话选择 debug 版本——选择 dev 分支——开始构建。
一般来说 Android 版本的打包过程还算顺利,但是 IOS 版本的打包过程就让人心碎了,下面我们来聊聊 IOS 版本:
首先仍旧是插件的打包,类似 Android 版本的打包过程,对于 IOS 不同的是版本选择 IOS ,分支选择 dev 点击开始构建。
IOS 的插件构建完成之后,类似的在京东商城选择 IOS——这里的 IOS JRdebug 版本是用来调试的版本,遗憾的是我们多次下载 JRdebug 版本在手机端总是打开之后闪退,还好 releaseP 版本也可以进行调试,虽然不是很方便,但也可以解燃眉之急:
1.4 手机安装APP
按照上述过程生成 APP, Android 版本的 APP 和 IOS 版本的 APP 接下来的步骤有所不同:对于 Android 版本:直接扫描构建平台——历史版本生成的二维码,安装京东 APP ,注意下面的步骤
打开 JDReact 调试模式;
如果使用的是真实环境,还需要在服务器设置中取消选择“前两项”,测试环境需勾选“前两项”;
每次安装完新的 APP 之后,一定要记得晃动手机,dev Seetings——设置 Debug server host & port for device 这个选项端口8081,如果报错 could not connect to development server ,需要检查一下防火墙是否打开了 8081 这个端口:控制面板——windows防火墙——高级设置——入站规则——新建规则——端口——特定本地端口:8081——选择允许联机连接——一直点击下一步。
对于 IOS 的 releaseP 版本:需要在构建平台——历史版本中找到打包好的 ipa 后缀文件,使用 itoos4 软件安装到 iphone 手机,该过程需要注意的是:
电脑端开启 npm start 服务(同样保证防火墙对端口 8081 的不限制);
手机连接电脑的 wifi ,手机浏览器登录跳转协议页面:
在列表输入框的链接改为自己电脑的 ip 地址和端口,文件名字改为自己的项目名,点击 React 按钮打开。
如果是真实环境,打开手机 APP 时,选择 api.jd.com 的环境,否则选择测试环境;
每次改动代码之后,需要退出后台的京东 APP ,然后先打开 APP ,选择 host 环境,最后在跳转协议列表页面重新用“ React 打开”按钮打开项目。
2 项目开发中的问题
在项目开发过程中遇到了很多问题,这里总结了几个具有代表性的问题:
2.1 JDImage 加载图片问题
使用 JDImage 组件加载本地图片和线上图片的方式是不一样的,如果不加注意很容易把两者混淆:
线上的图片直接使用uri:
<
JDImage
source
=
{{
uri
:
'http://xxx.jpg'
}}
style
=
{
styles
.
img0
}
/>
加载本地的图片使用的是require:
<
JDImage
source
=
{
require
(
'./images/xx1.jpg'
)}
style
=
{
styles
.
img1
}
/>
并且每次新增本地图片,控制台都会报错:…Unexpected character ‘◆'(1:0) at …
这是因为新增加的图片必须重新npm start。
2.2 通过路由完成页面之间的跳转
由于文档不全,路由之间如何传递参数,如何获取参数没有说明,导致在这里也花费了不少力气。对于页面之间的跳转,我们刚开始使用 JDRouter 中的 resetTo 方式进入某个路由:
1
2
3
4
|
this
.
context
.
router
.
reset
([
{
routeName
:
'index'
,
params
:
{
title
:
'apis'
}
},
{
routeName
:
'disCountPage'
,
params
:
{
datas
:
this
.
props
.
discountData
}
}
],
1
);
|
则下一个页面获取路由参数的方式是:
this
.
context
.
router
.
getCurrentRoutes
()[
1
].
params
.
title
;
随着项目开发,发现这样有个问题,例如从 A 页面跳转到 B 页面,如果从 B 页面回退到 A 页面,A 页面之前的操作状态会全部清空,因此,为了保留 A 页面的状态,改为使用 push 方式进入某个路由,用popToWithProps 返回上一个路由,这样的方法可以保留原页面的状态,但是如何获取路由携带的参数,文档中则没有介绍,经过多次尝试,我们发现需要这样设置:
A 页面通过 push 跳转到 B 页面并传参:
1
2
|
this
.
context
.
router
.
push
({
routeName
:
'B'
,
props
:
{
datas
:
this
.
props
.
discountData
}});
|
B 页面获取参数方式:
this
.
props
.
datas
.
data
,B 页面返回上一页面使用 popToWithProps,并传参:
this
.
context
.
router
.
popToWithProps
(
'A'
,{
trandatas
:
null
});
。A 页面获取参数方式:
this
.
context
.
router
.
getCurrentRoutes
()[
0
].
params
.
trandatas
2.3 修改底层组件
诚然 JDReact 底层封装的组件可以满足项目开发中的大部分需求,但是有些特殊需求,暂时不能满足,比如加油卡项目中设置密码的弹窗,设置按钮的字体在不同状态下要有对应的颜色,
该密码弹窗组件是在 JDConfirmDialog 组件的基础上开发的,但是该组件并没有提供确定按钮位置样式的变化,于是我们找到底层封装 JDConfirmDialog 组件的目录node_modules/@jdreact/Libraries/JDConfirmDialog/index.js文件,为了不影响底层组件,我们复制出该文件,在
1
2
3
|
<
JDText
style
=
{
styles
.
confirmText
}
>
{
this
.
props
.
confirmText
}
JDText
>
|
的位置增加可以传入设置文本的样式 textStyle:
1
2
3
|
<
JDText
style
=
{[
styles
.
confirmText
,
this
.
props
.
textStyle
]}
>
{
this
.
props
.
confirmText
}
JDText
>
|
这样就可以在组件外面设置按钮的样式了。
2.4 JDNetwork使用方法
-
在调取后台数据的时候走了很多弯路,首先是无法获取到后台发出的数据,debug 版本的京东 APP 默认的 host 是 api.m.jd.com.care ,后端使用 JSF 杰夫服务平台提供数据,前端使用 JDNetwork 组件给出的API:fetchWithoutHost 却无法调取后台数据,在此过程中,为了打通接口多次和不同团队进行了沟通咨询,最后发现,JSF 提供的数据前端无法直接使用,后端研发还需要再进行解析封装。
-
本以为数据接口只要调通了一个,其他的接口就问题不大了,然而却发现有的接口可以调通,有的接口却总是抛出错误,经过排查发现,只要后端返回的字段 code 不等于 0,就会抛出异常。这是怎么回事呢?经过询问才知道 code 作为保留字段,必须为 0 ,而不能作为业务含义(比如 code 表示用户的状态等等),否则一旦不等于 0 ,就表示 API 网关返回异常。
-
项目在测试环境中测试的差不多了,需要放在预发环境上,然而如何切换到预发环境上呢?需要配置 host 吗?需要修改代码吗?答案是不需要修改代码,从底层封装的组件可以看出我们使用的fetchWithoutHost ,其封装的 host 是 api.m.jd.com ,和 beta-api.m.jd.com , 分别对应着正式环境和测试环境,JDNetwork 写一套代码就可以。
对于 Android 版本的 APP:在 debug 的客户端中选择设置—— debug 配置——服务器设置——如果勾选前两项就是测试环境 api.m.jd.care(经过咨询得知 beta-api.m.jd.com 和 api.m.jd.care 都对应着测试环境,区别只在于 beta-api.m.jd.com 支持 https ,而 api.m.jd.care 这个网关是不支持 https ),如果去掉勾选前两项,host 就是 api.m.jd.com ;
对于 IOS 的 releaseP 版本则需要在点击“ React 打开”按钮启动 APP 时选择需要的 host 环境。
2.5 JDtext 换行问题
JDreact 组件开发的样式布局和常用的 H5 开发样式布局,多少还是有所不同。例如,项目中用户勾选协议部分如下图所示:
因为黑色字体使用
组件包裹,红色字体点击需要出现弹窗,所以红色字体部分需要使用点击组件
标签包裹,查看
底层代码可以看到里面是用
标签搭建的组件,所以
生成的黑色字体(行内元素)和 < JDTouchable> 包裹的红色字体(块级元素)无法像上图一样,只能分成多行显示:
这显然无法满足样式的需求,解决方法是红色的字体部分也使用
,点击事件放在
上面,并且用上一级的
嵌套,代码如下所示:
1
2
3
4
5
|
<
JDText
style
=
{{
fontSize
:
JDDevice
.
getFontSize
(
24
)}}
>
请您确认京东将收集您上述信息实现本服务,本服务约定请详见
<
JDText
onPess
=
{
this
.
_lookdeal
}
style
=
{{
fontSize
:
JDDevice
.
getFontSize
(
|