金先生的 NutUI3 初体验

avatar
UX @京东

金先生的诉求

冬日清晨,客服小王第一个来到了公司,还没顾得上脱下厚厚的羽绒服,桌上的电话就响了起来。“您好,这里是京东客服,请问有什么可以帮到您的么?”电话那头很嘈杂,呼啸的北风让来电人的声音很难被听清,而唯一可以被弄懂的就是对方一直在声嘶力竭反复强调的“......开票!......我要开票!......”

Invoicing wanted

业务娴熟的小王并没有慌乱,在办公桌前静候了几分钟后,电话铃声果然再次响起。 经过短暂几分钟的交谈,小王明白了来电人金先生的意图,在使用京东慧采 APP 购买到满意的商品后,开票环节的体验却比较差,每次都要找人帮忙处理,感觉很麻烦,希望能有一个自助开票的功能上线。

小王耐心地听金先生讲完后,便立刻展开了调查,原来京东慧采 APP 是一款专门面向大客户的购物平台,线上运行时间久,口碑也不错,小王稍作打听就顺利找到了慧采 APP 的研发人员。 在研发小哥哥那里,小王了解到:业务侧之前也做过调研,目前慧采 APP 的客户在使用开票功能的时候的确体验不佳,我们的商务及运营端对于发票处理的工作量也较大,开票时效无法提升,人力成本也很高。快速开发一个自助开票系统是很有必要的。

小王:“研发小哥哥,客户那边催的紧,咱们啥时候可以开发完这个功能呀?” 小王:“小哥哥,小哥哥,多久可以做好呀?”

小哥哥:“很快。”

小王:“......”

项目开发

develop with NutUI3

NutUI 是一套京东风格的移动端组件库,支持使用 Vue 在 H5和小程序端进行开发。小哥哥打开了 NutUI 官网 ,发现每半个月就会有一次大版本更新,并且最近几个版本又新增了好多组件:指示器组件、表格组件、骨架屏组件、级联选择器组件......不仅如此,组件库的设计风格也紧跟趋势,已然符合最新的京东 10.0 设计规范。 小哥哥打开了视觉稿,看到了铺满屏幕的几十张设计图,心中有些后悔和客服小王说了“很快”那两个字。但是看到入口页面后,他的眼中闪过一道光。 入口文件的这种设计,虽然看起来简单,但是也要考虑圆角、边界、间距、字体、右侧箭头等内容的开发与调整,而 NutUI 的单元格(Cell)组件却可以让整个开发时间缩减到极致。小哥哥思考着,敲下了几行代码:

<nut-cell-group>
     <nut-cell title="申请开票" is-link></nut-cell>
     <nut-cell title="开票提报申请单查询" is-link></nut-cell>
     <nut-cell title="发票换开查询" is-link></nut-cell>
     <nut-cell title="抬头资质管理" is-link></nut-cell>
</nut-cell-group>
<nut-cell title="历史发票" is-link></nut-cell>

1 分钟后,入口页面的重构基本完成了。 小哥哥打开了下一个页面“填写开票信息页”的视觉稿,这个页面是用来在开票过程中收集用户信息的,涉及到的功能较多,单看这上半部分就包含进度条、金额展示和开票方式的切换等功能。其他的功能暂且不提,单纯一个进度条的交互实现就需要花一点时间。

不过 NutUI 提供了一个步骤条(Steps)组件,在匹配度上极其吻合,引入组件后适当调整颜色即可使用。代码的编写上也只有几行。

<nut-steps :current="curPage">
    <template v-for="(item, i) in data" :key="i">
        <nut-step :title="item.name">{{ i }}</nut-step>
    </template>
</nut-steps>

小哥哥继续查看 NutUI 的文档,发现了价格(Price)组件和 单选按钮(Radio)组件

<nut-price :price="price" :decimal-digits="2" :need-symbol="true" :thousands="true" />
<nut-radiogroup v-model="radioVal" direction="horizontal">
      <template v-for="(item, i) in radioData" :key="i">
           <nut-radio shape="button" :label="item.name">{{ item.name }}</nut-radio>
      </template>
</nut-radiogroup>

价格(Price)组件中的 thousands 属性可以控制是否按照千分号形式显示,这样就无需去处理价格字段再手动添加逗号;同时,也可以自定义小数位数,设置是否展示人民币符号"¥"等。

单选按钮(Radio)组件在这里难以在第一时间想到它,因为开票方式的选择按钮,更容易让人联想到按钮(Button)组件,不过依据一次只能选择一个的逻辑,使用单选按钮(Radio)组件将带来更快捷的开发体验。

很快,小哥哥把第一期需求开发完成了。

精益求精

optimize with NutUI3

又是一个美好的早晨,金先生找到了客服小王,衷心感谢了小王及其同事们所做出的种种努力,并表示,如果能在用户体验上再优化一下,他会更爱大家。

小王受到了表扬很开心,也立刻找到了研发小哥哥。 小哥哥:“哦。”

一大早就“很有干劲”的小哥哥只得继续到 NutUI 文档 中寻求帮助,却很顺利地就发现了滚动加载(InfiniteLoading)组件,不禁心头一喜:“要啥有啥,真棒。”

类似这种信息列表,如果是直接把数据全部取到然后列出来的确不太友好,让用户拉到底部后再加载更多的内容,在性能和用户体验上都是一种更优的选择。

那么,下拉加载要怎么写?核心的思路就是监听用户滑动到了底部后再次请求接口获取分页数据,而使用 NutUI 滚动加载(InfiniteLoading)组件可以这样写:

<nut-infiniteloading
    :has-more="hasMore"
    :use-window="false"
    container-id="search-list"
    load-more-txt="没有更多数据啦~"
    @load-more="getMore"
>
     <div>
           <!-- 这里是要展示的内容,此处就是列表信息 -->
     </div>
</nut-infiniteloading>

has-more 用来标识是否还有更多数据以展示触底文案,load-more 为继续加载的回调函数。 刚刚优化了下拉加载功能的小哥哥意犹未尽,觉得可以再做一点事情,片刻思考后他想到之前开发过程中,NutUI 组件库并未提供 表单(Form)组件,他便提了一个 Issue ,不知道现在有没有人回复他。

小哥哥打开 github,惊奇地发现 NutUI 团队的小伙伴已经热情地回复了他,并且表单(Form)组件也已经跟随最新版本发布上线。带着试试看的心情,小哥哥打算重构一下之前纯手写的“新增普票收票人地址”页面。

<nut-form>
    <nut-form-item label="姓名">
        <input class="nut-input-text" placeholder="请输入姓名" type="text" />
    </nut-form-item>
    <nut-form-item label="电话">
        <input class="nut-input-text" placeholder="请输入年龄" type="text" />
    </nut-form-item>
    <nut-form-item label="所在地区">
        <input class="nut-input-text" placeholder="请输入联系电话" type="text" />
    </nut-form-item>
    <nut-form-item label="详细地址">
        <input class="nut-input-text" placeholder="请输入地址" type="text" />
    </nut-form-item>
</nut-form>

不得不承认,开发这个组件的小伙伴还是很给力的,按照文档把代码写下来后,距离实际的需求完成就已经很近了。

简单的总结

make a summary

  • 一个清晨,客户金先生寻求帮助,希望可以自助开票;
  • 客服小王找到研发小哥哥;
  • 时间紧、任务重,小哥哥使用 NutUI 组件库 进行开发;
  • 过程很顺利,结果很美好;
  • 又一个清晨,客户金先生提出优化需求;
  • NutUI 组件库再登场
  • 客户金先生很满意,项目就叫——金如意。