Skip to content
On this page

实战篇 7-结算页面开发


结算页面开发

上一章我们讲解了购物车页面,而在购物车页面点击「去结算」便会进入结算页。结算页也是在购物流程里十分重要的页面,一般用户会在这里选择收货地址、付款方式、发票等,并进行最终的付款流程。本章我们将进行结算页的讲解。

页面布局

先来看一眼页面结构:

页面结构

可以见到,整个页面的布局分为三大块内容,分别是:

  • 收货地址,结算商品模块;主要是选择收货地址和结算商品的展示
  • 支付信息模块,包括支付方式,优惠券等;主要是支付方式的选择以及优惠券的使用
  • 结算总金额模块,展示支付总额。

在 JSX 上,页面结构如下所示,十分清晰:

<View className='balance'>
  <View className='balance_good'>...</View>
  <View className='balance_pay'>...</View>
  <View className='balance_amount'>...</View>
  <View className='balance_bottom'>...</View>
</View>

从布局可以看出,页面的整体逻辑并不是特别复杂,逻辑比较集中的地方是结算商品数据的拉取与显示地址,优惠券,支付方式的选择支付逻辑吸底地址栏与弹出层的动画实现。不过在第 18 章 《通过小程序云搭建电商后台服务》一文中已提到,我们实现的只是最简单的电商流程,所以 Demo 中并没有实现地址模块与优惠券模块,在这个页面里显示的相关内容只是虚拟数据。因此,下面重点讲述的是数据的拉取与显示动画实现

结算商品的数据拉取与显示

上一节中说过,有一些模块采用的是假数据,而真正从数据中拉取数据的是红色框框住的部分,主要是需要结算的商品数据与结算底栏。仅仅从页面结构中也可以看出,相较于购物车页,这里的逻辑是十分简单的,仅仅就是拉取数据,渲染数据就行了。所以我们要做的主要工作是数据的处理。

const data = result.data // result 为接口返回的数据
const balanceData= handleBalanceData(data) // handleCartData 为处理数据的函数
dispatch({type: 'RECEIVE_BALANCE_INFO', payload: balanceData}) // dispatch 处理过后的函数

...
// handleBalanceData 处理后的数据
{
    payCommodities: [{
        shop: {...},  // 商品店铺的信息
        goods: {...}, // 对应商品信息
    }, ...],
    isNeedBanlance,   // 是否需要结算
    payNum,           // 总的商品数量
    totalPrice        // 总结算金额
}

看过我们上一章购物车的读者应该都知道,这里的处理是类似的,都是数据渲染前的预处理。将接口拉到的结算页数据处理为方便直接渲染的结构,分别是 结算商品数据总的商品数量总结算金额,对应着上图两个红框。isNeedBanlance 这个值比较特殊,主要是为了预防一些意外的情况,例如在没有结算商品的情况下进入了结算页,这时候这个值就是 false,然后会进行一个处理,自动跳转到购物车页。

页面动画实现

动画这个,在前面的章节几乎完全没有提及,但其实每个页面或多或少都会有些动画效果,只是受限于篇幅没有讲解。现在结算页逻辑不算太复杂,所以我们在这里就主要说下该页面的两个动画,分别是吸底地址栏浮层弹出动画

吸底地址栏

a

在 GIF 中可以看到,滚动到顶部时,地址栏渐隐;滚动到非顶部时,出现吸底地址栏,并且有渐现动画。显然,我们需要小程序的 onPageScroll API,用于监听页面的滚动事件,函数部分代码如下:

onPageScroll (e) {
  // e.scrollTop 为 0,且 this.state.reachTop 为 false
  if (!e.scrollTop && !this.state.reachTop) {
    this.setState({
      reachTop: true
    })
  }

  if (this.state.reachTop) {
    this.setState({
      reachTop: false
    })
  }
}

// ...JSX
<View className={reachTop ? 'balance_addr top' : 'balance_addr'}>
    <View className='balance_addr_icon' />
	<Text className='balance_addr_text'> 广东省深圳市宝安区龙光世纪大厦 </Text>
</View>

// ...scss
balance_addr {
	// ....
    opacity: 1;
    transition: opacity 300ms ease;
    &.top {
        opacity: 0;
    }
}

e.scrollTop 为 0,且 this.state.reachTopfalse 时,将 this.state.reachTop 设置为 true,说明已经到达顶部。同时可以在 JSX 里见到,在到达顶部时地址栏容器的类名会多一个 top,将透明度变为 0,再配合 transition 展示出渐隐渐现的动画效果。

选项弹出层 - ActionSheet

通过 GIF 可以看到,这个动画比吸底地址栏的渐隐渐现稍显复杂,主要包含 ActionSheet 的进场动画和离场动画。如果只通过一个状态控制浮层的展示与隐藏,并不能实现在进场和离场时都有动画,例如入下面的代码:

showMask && <View className='paybox'>...</View>

这样会发现,在控制隐藏时,浮层是直接从 DOM 结构中移除的,会导致没有隐藏部分的动画。

所以,我们用了两个状态控制,分别用于控制 DOM 的隐藏及离场的动画显示。代码如下:

showPayWay &&
<View className={aniShowPayWay ? 'balance_pay_choose show' : 'balance_pay_choose'}>
  <View className='mask' onAnimationEnd={this.onAnimationEnd}></View>
  <View className='main'>...</View>
</View>

// onAnimationEnd
// 监听隐藏动画已结束,再将浮层从 DOM 中移除
onAnimationEnd () {
  if (!this.state.aniShowPayWay) {
    this.setState({
      showPayWay: false
    })
  }
}

// ..scss
&.show {
    opacity: 1;
    z-index: 10;
    .mask {
        animation-name: showPanelMask;
    }
    .main {
        animation-name: showDetailWrapper
    }
}
.mask {
    animation-name: hidePanelMask;
}
.main {
    animation-name: hideDetailWrapper;
}

aniShowPayWay 用于控制进场动画和离场动画,可以见到,是否有 show 样式类名会决定执行的是进场还是离场动画。同时对动画进行事件监听,假如是离场动画结束(this.state.aniShowPayWayfalse),则隐藏 DOM。至此,进场离场的动画便能完成实现。

支付模块

支付模块可以说是结算页面的最主要的部分了,一个普通的电商程序的支付流程一般如下:

  1. 提交订单请求,后台生成订单,同时返回生成的订单号
  2. 调取微信接口取得用户参数,同时请求生成支付相关信息的接口,而后台返回数据包,签名数据等
  3. 根据后台返回的支付数据,调取微信小程序 Taro.requestPayment API,唤起支付

也就是说,这里请求了两次,先是请求生成订单并得到订单号;第二次根据订单号和用户信息,再次请求,获得调取支付的各种信息,最后再调取支付。

这里值得注意的点就是第二次请求需要支付相关的 userinfoivencryptedData,而这些信息需要通过 Taro.getUserInfo 接口拿到,但由于接口调整的原因,在用户未授权的情况下,调取该接口不再弹出浮层提示用户授权,而是需要用户手动去点击小程序中 open-typegetUserInfobutton 组件以进行授权。(具体细节可以查看本小册第 23 章《 微信小程序端用户授权处理》)。所以我们在全局维护一个是否授权字段时,若未授权,则点击支付时再弹出自己模拟的模态框引导用户授权。

PS:需要说明的是,由于跑通真实的支付流程是需要商家证书等一系列认证,所以我们的 Demo 并没有跑通真正的支付,而只是会生成一个订单,上面仅作支付流程唤起的讲解。

小结

本文从页面布局数据拉取与展示动画实现支付模块 这四个方面来阐述如何使用 Taro 开发结算页,整体的开发难度相较购物车可能有一定的下降,但同样也是电商黄金流程中十分重要的一环。

下一章我们将介绍小程序用户端的授权处理。