项目背景介绍

4号得到消息要做一个紧急项目,双十一当晚10点30分,北京水立方,美国纽约证券交易所为“2015天猫双十一全球狂欢节”举行远程开市敲钟仪式,见证这场全球商业的狂欢。到时马大大会和8位曾获得阿里公益“天天正能量”奖的人物代表举行远程开市敲钟仪式,这是纽交所首次为一家中国的互联网企业举行远程敲钟仪式。我负责在手淘上开发一个敲钟功能,让手淘的一亿多用户能够在手机上和马总一块敲响开市钟。

screenshot

项目特点

快,时间紧迫,需要在短时间内完成需求以及应对各种变更 变,这种大老板拍的需求充满变数,因为pd觉得好还不行,还得大老板拍板。但是大老板们又很忙,没办法及时拍板。所以只能先按照PD的意愿做出来。心理和代码上都得做好快速应对可大可小变数的准备。 质,代码质量要求够高,减少bug量,缩短测试时间

项目开发过程

页面是放在poplayer里面展示的,什么是poplayer呢,它就是手淘在native界面上覆盖了一个新的webview容器,然后这个webview是透明的,透过这个webview还能看到底下的页面。这样需要在native页面上增加一些内容时就不用发版,更灵活。开发过程和普通手机浏览器里的页面是一样的,只需要在适当的时间调用手淘开放的方法打开和关闭poplayer。更多关于poplayer的介绍详见:f#18

由于时间不够充裕,没办法等视觉稿出来再开发,所以前端和视觉同时开工。这个项目使用的是reactjs开发,react通过数据来控制DOM的特性,js里没有了对DOM的操作,让我们可以在脱离视觉稿的情况下进行页面逻辑部分的编码。 大致的开发过程如下。首先,根据需求内容将页面拆分成6个状态

/*
    pageStatus:
        SmallPreTip: 等待开始的悬浮icon
        SmallStartTip: 开始抽奖的悬浮icon
        Error: 错误页
        CountdownWait: 显示倒计时等待页面
        RefreshWait: 显示刷新等待页面
        WaitAward: 显示抽奖页面
        AwardSuccess: 中奖了
        AwardFail: 没中奖
*/

每个状态对应于一个component,每个component里面通过props特性来和父级元素通信。

screenshot

最终通过修改数据来控制页面的内容

         switch(pageStatus) {
                case 'SmallPreTip':
                    content = (
                        <SmallTip start="false"></SmallTip>
                    )
                    break;
                case 'SmallStartTip':
                    content = (
                        <SmallTip start="true"></SmallTip>
                    )
                    break;
                case 'Error':
                    content = (
                        <ErrorCom></ErrorCom>
                    )
                    break;
                case 'CountdownWait':
                    content = (
                        <PopPreTip countdown="true" leftTime={this.state.leftTime}></PopPreTip>
                    )
                    break;
                case 'RefreshWait':
                    content = (
                        <PopPreTip refresh="true"></PopPreTip>
                    )
                    break;
                case 'WaitAward':
                    content = (
                        <WaitAward uid={this.state.uid}></WaitAward>
                    )
                    break;
                case 'AwardSuccess':
                    content = (
                        <AwardSuccess></AwardSuccess>
                    )
                    break;
                case 'AwardFail':
                    content = (
                        <AwardFail></AwardFail>
                    )
                    break;
                default:
                    content = null;
                    break;
            }

搭建好大的展示模型后,就是接口调用和结果处理了。在这个项目里,我将所有api调用放在一个js文件里集中处理。

param.doSee = {
    api: 'mtop.taobao.aplatform.get',
    v: '1.0',
    ecode: 1,
    data: {
        bizType: 'zhong.go',
     }
};

function mtopError(ret,errorCallback) {
    errorCallback && errorCallback(ret);
}

var api = {};
for (let i in param) {
    api[i] = function(){
        var p = new Promise(function(resolve,reject) {
            mtop.request(param[i],function(ret){
                resolve && resolve(ret);
            },function(ret){
                mtopError(ret,reject)
            })
        })
        return p;
    }
}

也就是说,如果我需要调用新的api,只需在param里新增一项内容,无需再去重复编码mtop的调用部分,而且对于mtop的异常返回可以做一些共用的处理。 在需要调用api的地方,也不必太关注api的入参部分,只需处理返回结果就行。 mtop 是手淘这边封装好的调用接口的组件库,可以理解成一个普通的jsonp请求。

api.getPageStatus().then((ret) => _getPageStatusSuccess(ret.data,params),(ret) => _getPageStatusFail(ret,params));

最后根据接口的返回,根据需要控制pageStatus的值就可以。 将页面逻辑写完,待视觉稿出来,只需根据视觉稿逐一完成各子组件里的样式部分、动画部分和交互部分。

这种开发模式的优点除了可以和设计同行外,最主要的还是页面层级结果清晰,出问题是能够快速定位。这个项目,最终的开发时间是2.5d,6号开始开发,8号下午就提测了。视觉定稿是在开发的最后一天出来的,当然不可避免之后又修改了一版。 测试适配阶段几乎0bug,除了一些图片加载不出来我只能wontfix的bug,后期图片都是会使用手淘的zcache功能提前缓存到本地,可以避免这个问题。刚开始PM还担心适配会出现很多问题,害怕时间不够。但是自从使用了flib-flexible,基本适配无压力。lib-flexible的适配分成两种方案,dpr(根据设备的devicePixelRatio来设置不同的size,单位是px)和rem(根据屏幕宽度定义1rem=x px,然后单位用rem),基本弄清楚什么时候该用哪个就没问题了。坚持三个原则:

  • 字号dpr,其他用rem
  • 容器里如果有文字并且不能折行,容器相关的设置也应当用dpr
  • 如果是那种文字必须在一行展示完,但是字又比较多的情况,则字也用rem。当然这种情况必须提前跟视觉沟通好,不建议自己单独使用,否则后面容易返工。

关于flexible的更多介绍,可以看一下大漠爷爷的这篇文章f#17

总的来说,这个距离双十一不到一周的时间里提出来的项目还是挺成功的,10号就完成上线,距离11号开放入口还有一天的buffer,上线后也没有出现任何问题,直至下线。当然项目本身比较简单,然后PD的想法和大老板想法比较吻合,后期没什么变更。

高效的开发离不开工具,推荐使用以下几个工具:

  • fgulp-px3rem自动换算css里px到rem
  • fautoprefixer 自动给高级css3属性带上各种前缀,减少适配问题
  • fwebpack&babel 转换jsx和es6语法,麻麻再也不用担心我用react和es6了