Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

双十一敲钟项目总结 #19

Open
qingying opened this issue Nov 20, 2015 · 3 comments
Open

双十一敲钟项目总结 #19

qingying opened this issue Nov 20, 2015 · 3 comments

Comments

@qingying
Copy link

项目背景介绍

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

项目特点

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

项目开发过程

页面是放在poplayer里面展示的,什么是poplayer呢,它就是手淘在native界面上覆盖了一个新的webview容器,然后这个webview是透明的,透过这个webview还能看到底下的页面。这样需要在native页面上增加一些内容时就不用发版,更灵活。开发过程和普通手机浏览器里的页面是一样的,只需要在适当的时间调用手淘开放的方法打开和关闭poplayer。更多关于poplayer的介绍详见:#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还担心适配会出现很多问题,害怕时间不够。但是自从使用了lib-flexible,基本适配无压力。lib-flexible的适配分成两种方案,dpr(根据设备的devicePixelRatio来设置不同的size,单位是px)和rem(根据屏幕宽度定义1rem=x px,然后单位用rem),基本弄清楚什么时候该用哪个就没问题了。坚持三个原则:

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

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

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

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

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

kujian commented Nov 22, 2015

好文章,样式和逻辑分离,一边设计一边开发。赞

@shenjianzch
Copy link

开源么 只想知道这个。。。不然说再多也无用啊

@minminma
Copy link

请问手淘现在兼容适配的范围是怎样的?包括wp吗?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants