zoukankan      html  css  js  c++  java
  • 如何用Baas快速在腾讯云上开发小程序-系列4:实现客户侧商品列表、商品详情页程序

    版权声明:本文由贺嘉  原创文章,转载请注明出处: 
    文章原文链接:https://www.qcloud.com/community/article/431172001487671163

    来源:腾云阁 https://www.qcloud.com/community

    如何用Baas快速在腾讯云上开发小程序-系列4:实现客户侧商品列表、商品详情页程序

    一、实验简介
    通过实现商品列表、商品详情页程序,熟练掌握云端数据表查询操作。

    二、实验目标

    1. 掌握小程序调试方法
    2. 掌握小程序操作云端数据方法
    3. 掌握云端数据表增删改查操作

    三、实验步骤
    3.1 Hello World

    1. 应用设置
      第一步: 修改 app.js ,初始化全局对象

      1. App({
      2. onLaunch: function () {
      3. // 创建 xpm 对象
      4. this.xpm = require('xpmjs/xpm.js').option({
      5. 'host':'wss.appcook.cn',
      6. 'https':'wss.appcook.cn',
      7. 'wss': 'wss.appcook.cn/ws-server',
      8. 'table.prefix': 'hello',
      9. 'user.table':'user'
      10. });
        12.
      11. // 创建全局对象 this.wss = this.xpm.require('wss'); // 信道
      12. this.session = this.xpm.require('session'); // 会话
      13. this.stor = this.xpm.require('stor'); // 存储17. this.utils = this.xpm.require('utils'); // 工具
      14. this.user = this.xpm.require('user'); // 用户19. },
      15. xpm:null,
      16. user:null,
      17. utils:null,
      18. session:null,
      19. stor:null,
      20. wss:null
      21. })

    第二步: 修改 app.json 添加页面清单,修改标题栏默认属性

    1. {
    2. "pages":[
    3. "pages/index/index"
    4. ],
    5. "window":{
    6. "backgroundTextStyle":"light",
    7. "navigationBarBackgroundColor": "#ffffff",
    8. "navigationBarTitleText": "Hello World",
    9. "navigationBarTextStyle":"black"
    10. }
    11. }
    

    第三步: 修改 app.wxss 设定全局样式

    1. .container {
    2. height: 100%;
    3. display: flex;
    4. flex-direction: column;
    5. align-items: center;
    6. justify-content: space-between;
    7. padding: 100rpx 0;
    8. box-sizing: border-box;
    9. }
    

    2. 用户登录
    第一步: 修改 pages/index/index.js 用户登录代码

    1. var app = getApp();
    2. Page({
    3. data: {
    4. hello: 'hello world',
    5. userInfo: {
    6. avatarUrl:'http://of2is3ok3.bkt.clouddn.com/nopic.gif',
    7. nickName:'载入中..'
    8. }
    9. },
    10. onLoad: function () {
    11. var that = this;
    12. app.user.login().then(function( uinfo ){
    13. that.setData({userInfo:uinfo});
    14. });
    15. }
    16. });
    

    第二步: 修改 pages/index/index.wxml 更新页面布局

    > 1. <view class="container">
    > 2. <view bindtap="bindViewTap" class="userinfo">
    > 3. <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" backgro und-size="cover"></image>
    > 4. <text class="userinfo-nickname">{{userInfo.nickName}}</text>
    > 5. </view>
    > 6. <view class="usermotto">
    > 7. <text class="user-motto">{{hello}}</text>
    > 8. </view>
    > 9. </view>
    

    第三步: 修改 pages/index/index.wxss 微调页面样式

    1. .userinfo {
    2. display: flex;
    3. flex-direction: column;
    4. align-items: center;
    5. }
    6.
    7. .userinfo-avatar {
    8.  128rpx;
    9. height: 128rpx;
    10. margin: 20rpx;
    11. border-radius: 50%;
    12. }
    13.
    14. .userinfo-nickname {
    15. color: #aaa;
    16. }
    17.
    18. .usermotto {
    19. margin-top: 120px;
    20. }
    

    第五步: 修改 pages/index/index.json 设置页面名称

    1. {
    2. "navigationBarTitleText": "用户登录
    

    效果预览: 通过微信开发者工具,通过模拟器可以实时预览效果

    3.2 商品列表页
    1. 全局样式表
    在小程序中有两种方式使用全局样式。在 app.wxss中定义的样式为全局样式;也可以通过
    @import "common.wxss"; 方法引用样式表文件。为了便于修改前台样式,我们定义一个通用的样式文件 pages/wxss/style.wxss 。
    创建 pages/store/wxss/style.wxss 前台通用样式文件; 下为代码片段,完成代码参见源码。

    1. view {
    2. color:#232323;
    3. font-size:32rpx;
    4. }
    5.
    6. button[type="primary"][plain] {
    7. border: 1px solid #81c7d1;
    8. color: #81c7d1;
    9. }
    10.
    11. button[type="primary"] {
    12. color:#FFFFFF;
    13. background-color:#81c7d1;
    14. }
    15.
    16. .topbar{
    17. background: #f5f5f5;
    18. line-height: 64rpx;
    19. position: fixed;
    20.  100%;
    21. z-index: 1000;
    22. border-bottom: 2rpx solid #e1e1e1;
    23. }
    24. ...
    

    2. 购物车布局
    因为有多个页面,用到了购物车底栏; 所以将购物车布局代码抽离成独立文件使用

    标签引入。
    创建购物车 pages/store/common/cart.wxml 代码文件。

    1. <view class="bottombar view-row">
    2. <view style="88rpx;">
    3. <image mode="widthFix" src="/res/icons/shop.png"></image>
    4. </view>
    5. <view style="40%">
    6. <text style="padding-left:20rpx;"> {{cart.total}} 件商品 {{cart.show
    _price}} 元 </text>
    7. </view>
    8. <view class="text-right" style="50%">
    9.
    10. <button
    11. class="push-t-10 push-r-10"
    12. type="default" size="mini" loading="{{loading}}"
    13. disabled="{{disabled}}"
    14. bindtap="cleanup"> 清空 </button>
    15. <button
    16. class="push-t-10 push-r-10"
    17. type="warn" size="mini" loading="{{loading}}"
    18. disabled="{{disabled}}"
    19. data-link="{{order}}" bindtap="payout"> 结算 </button>
    20. </view>
    21. </view>
    

    3. 购物车、商品信息过滤功能模块
    对于不同会员来说,每件商品有不同价格,商品信息过滤功能和购物车也在多个页面用到,将购物车、商品信息过滤等功能封装成对象,在不同页面中复用。
    创建 utils 目录, 创建 goods.js 文件

    1. function Goods( user, session ) {
    2.
    3. var that = this;
    4.
    5. this.user = user;
    6. this.ss = session;
    7. this.sname = '_cart_' + this.user['_id'];
    8. this.suinfo = '_cart_' + this.user['_id'] + '_uinfo';
    9.
    10.
    11. // 生成订号
    12. this.genOrderSN = function() {
    13. var timestamp = (new Date()).valueOf();
    14. return timestamp.toString() + Math.ceil(Math.random()*1000).toS
    tring();
    15. }
    16.
    17.
    18. // 根据会.信息, 处理价格
    19. this.price = function( real_price ) {
    20. return real_price['member'];
    21. }
    22.
    23.
    24. // 处理商品字段
    25. this.fliter = function( goods ) {
    26.
    27. for( var i =0 ; i<goods.length; i++ ) {
    28. var price = new Number(this.price(goods[i]['real_price']));
    29. goods[i]['sale_price'] = price;
    30. goods[i]['show_price'] = (price/100).toFixed(2).toString();
    31. }
    32.
    33. return goods;
    34. }
    35.
    36. this.cart = {
    37.
    38. order: function( data ) {
    39. var cdata = that.ss.get(that.suinfo) || {};
    40.
    41. if ( typeof data != 'object' ) {
    42. cdata['address'] = cdata['address'] || that.user['addr_
    01'];
    43. cdata['mobile'] = cdata['mobile'] || that.user['mobile'
    ];
    44. cdata['contact'] = cdata['contact'] || that.user['nickN
    ame'];
    45. that.ss.set(that.suinfo, cdata);
    46. } else {
    47. cdata['address'] = data['address'] || cdata['address'];
    48. cdata['mobile'] = data['mobile'] || cdata['mobile'];
    49. cdata['contact'] = data['contact'] || cdata['contact'];
    50. that.ss.set(that.suinfo, cdata);
    51. }
    52.
    53. return cdata;
    54. },
    55.
    56.
    57. add: function( id, price, amount ) {
    58.
    59. var data = that.ss.get(that.sname) || {};
    60.
    61. if ( typeof data[id] == 'object' ) {
    62. data[id]['amount'] = new Number(data[id]['amount'])
    + new Number(amount);
    63. } else {
    64. data[id] = { id:id, price:price, amount:amount };
    65. }
    66. that.ss.set(that.sname, data);
    67. },
    68.
    69.
    70. rm: function( id, amount ) {
    71. var data = that.ss.get(that.sname) || {};
    72.
    73. if ( typeof data[id] == 'undefined' ) {
    74. return;
    75. }
    76.
    77. data[id]['amount'] = new Number(data[id]['amount']) - new N
    umber(amount);
    78. if ( data[id]['amount'] <= 0 ) {
    79. try { delete data[id] } catch( e ){}
    80. }
    81. that.ss.set(that.sname, data);
    82. },
    83.
    84. remove: function( id ) {
    85. var data = that.ss.get(that.sname) || {};
    86. try { delete data[id] } catch( e ){}
    87. that.ss.set(that.sname, data);
    88. },
    89.
    90. clean: function(){
    91. that.ss.set(that.sname, {});
    92. },
    93.
    94. total: function() {
    95. var amt=0, fee=0, show='0.00';
    96. var data = that.ss.get(that.sname) || {};
    97.
    98. for( var k in data ) {
    99. var iamt = new Number(data[k]['amount']);
    100. amt = new Number(amt) + iamt;
    101. fee = new Number(fee) + ( new Number(data[k]['price']) *
    iamt );
    102. }
    103.
    104. var price = new Number(fee);
    105. show = (price/100).toFixed(2).toString();
    106. return {total:amt, sale_price:fee, show_price:show };
    107. },
    108.
    109. get: function() {
    110. return that.ss.get(that.sname) || {};
    111. }
    112. }
    113.
    114. }
    115.
    116. module.exports = Goods;
    

    4. 商品列表页
    创建 pages/store/products 目录,在目录下创建 list.js , list.wxml 和 list.wxss 文件。
    第一步: 将页面添加到 app.json

    1. {
    2. "pages":[
    3. "pages/store/products/list",
    4. "pages/index/index",
    5. "pages/logs/logs",
    6. "admin/table/index"
    7. ],
    8. "window":{
    9. "backgroundTextStyle":"light",
    10. "navigationBarBackgroundColor": "#fff",
    11. "navigationBarTitleText": "Hello World",
    12. "navigationBarTextStyle":"black"
    13. }
    14. }
    

    第二步: 修改 pages/store/products/list.wxml 页面布局

    1. <scroll-view scroll-y="true" style="height:{{system.windowHeight}}px;">
    2. <view class="table-list">
    3. <view class="row border-item-1 pad-10" style="padding-top:26
    rpx;" wx:for="{{goods}}" wx:key="_id" >
    4. <view style="200rpx;" class="push-r-10"> <image
    bindtap="detail" data-id="{{item._id}}" mode="widthFix" src="{{item.
    corver}}"></image> </view>
    5. <view style="50%" class="push-r-10"><text bindtap="de
    tail" data-id="{{item._id}}" class="font-s15">{{item.name}}</text>
    </view>
    6. <view style="30%" class="push-r-10 push-t-10"> <text
    bindtap="detail" data-id="{{item._id}}" class="textprimary">{{
    item.show_price}}</text> </view>
    7. <view style="30%;min-160rpx;">
    8. <button type="primary" size="mini" bindtap="addtocard"
    9. data-id="{{item._id}}"
    10. data-price="{{item.sale_price}}"
    11. data-amount="1"
    12. bindtap="addtocart">购买</button>
    13. </view>
    14. </view>
    15.
    16. <view class="row border-item-1 pad-10 {{goodsLoading}}" style=
    "padding-top:26rpx;">读取中...</view>
    17. <view class="phrow"></view>
    18. </view>
    19.
    20. <include src="../common/cart.wxml" />
    21. </scroll-view>
    

    第三步: 修改 pages/store/products/list.wxss 页面样式

    1. @import "../wxss/style.wxss"
    2.
    3. .bottombar {
    4. bottom: 0px;
    5. border: 1px solid #81c7d1;
    6. background: #81c7d1;
    7. color:#ffffff;
    8. position: fixed;
    9. line-height: 100rpx;
    10. height:100rpx;
    11.  100%;
    12. z-index: 1000;
    13. }
    14.
    15. .bottombar text {
    16. color: #ffffff;
    17. font-weight: 400;
    18. font-size: 30rpx;
    19. }
    20. .bottombar image {
    21.  60rpx;
    22. height: 60rpx;
    23. margin:20rpx;
    24. margin-bottom:0;
    25. }
    26. .text-mimi{
    27. font-size: 25rpx;
    28. color: #81c7d1;
    29. margin-left: 10rpx;
    30. }
    

    第四步: 修改 pages/store/products/list.js 添加读取商品逻辑

    1. var Goods = require("../../../utils/goods.js");
    2. var app = getApp();
    3. Page({
    4.
    5. data:{
    6. system:{},
    7. paginate:{},
    8. goods:[],
    9. cart:{},
    10. goodsLoading:'',
    11. lock: false
    12. },
    13.
    14. // 链接到详情页
    detail:function(e){
    16. var data = e.target.dataset;
    17. wx.navigateTo({ url: '/pages/store/products/detail?id=' + data.
    id });
    18. },
    19.
    20. loading: function() {
    21. this.lock = true;
    22. this.setData( {goodsLoading:''} );
    23. },
    24.
    25. done: function() {
    26. this.lock = false;
    27. this.setData( {goodsLoading:'hidden'} );
    28. },
    29.
    30.
    31. // 读取商品信息
    32. getGoods: function ( page ) {
    33.
    34. var that = this;
    35. page = page || 1;
    36.
    37. return new Promise( function( resolve, reject ) {
    38.
    39. that.goods.query()
    40. .where('status', '=', 'online')
    41. .paginate( 10, page )
    42.
    43. .fetch('*').then(function(resp) {
    44.
    45. resp.next_page = resp.current_page + 1;
    46. if ( resp.next_page > resp.last_page ) {
    47. resp.next_page = resp.last_page;
    48. }
    49.
    50. resolve({
    51. paginate:{
    52. curr:resp.current_page,
    53. next:resp.next_page,
    54. last:resp.last_page,
    55. total:resp.total
    56. },
    57. goods:that.storeUtils.fliter(resp.data)
    58. });
    59.
    60. }).catch(function( excp ){
    61. reject(excp);
    62. })
    63.
    64. });
    65. },
    66.
    67. onLoad:function( params ) {
    68.
    69. var that = this;
    70. this.goods = app.xpm.require('Table','goods');
    71.
    72. // 设置页面高度
    this.setData({'system':wx.getSystemInfoSync()});
    74. console.log( this.data );
    75.
    76. // 用户登录
    app.user.login().then( function( userInfo ) {
    78. that.storeUtils = new Goods( userInfo, app.session );
    79. that.setData({cart:that.storeUtils.cart.total()}); // 初始
    化购物车信息
    81. return that.getGoods(); // 读取商品列表
    82.
    }).then( function( resp ) {
    that.setData( resp );
    85. that.done();
    86. });
    87. },
    88.
    89. goods:null, // 商品表
    90. storeUtils:null, // 商店工具对象 
    

    第五步: 修改 pages/store/products/list.json 修改标题

    1. {
    2. "navigationBarTitleText": "商品列表"
    3. }
    

    5. 滑到底部追加数据
    第一步: 修改 pages/store/products/list.wxml 绑定 bindscrolltolower 事件

    1. <!-- 将标签 -->
    2. <scroll-view scroll-y="true" style="height:{{system.windowHeight}}px;">
    3.
    4. <!-- 修改为-->
    5. <scroll-view scroll-y="true" bindscrolltolower="next" style="height:{{s
    ystem.windowHeight}}px;">
    

    第二步: 修改 pages/store/products/list.js 添加 next 属性

    1. ...
    2. next: function( e ) {
    3. var that = this;
    4. if ( this.lock ) return;
    5. if ( this.data.paginate.next == this.data.paginate.curr ) retur
    n;
    6.
    7. this.loading();
    8. this.getGoods( this.data.paginate.next ).then( function(resp )
    {
    9. var goods = that.data.goods;
    10. for( var i in resp.goods ) {
    11. goods.push(resp.goods[i]);
    12. }
    13. that.setData( {paginate: resp.paginate, goods:goods} );
    14. that.done();
    15. });
    16. },
    17. ...
    6. 购物车相关功能
    修改 pages/store/products/list.js 添加 addtocart 、cleanup 和payout 属性
    1. // 购物车.算
    2. payout: function(e) {
    3. wx.navigateTo({ url: '/pages/store/order/confirm/confirm' });
    4. },
    5.
    6. // 清空购物车
    7. cleanup: function(e) {
    8. this.storeUtils.cart.clean();
    9. this.setData({cart: this.storeUtils.cart.total()});
    10. },
    11.
    12. // 添加到购物车
    13. addtocart: function( e ) {
    14. var data = e.target.dataset;
    15. this.storeUtils.cart.add(data['id'], data['price'], data['amoun
    t']);
    16. this.setData({cart: this.storeUtils.cart.total()});
    17. },
    

    四、实验结果
    通过本实验,熟练掌握小程序调试方法;熟悉数据表查询操作。

  • 相关阅读:
    Redisson 实现分布式锁原理分析
    redis如何避免释放锁时把别人的锁释放掉
    记一次org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only异常
    1.编译chromium
    Win10更新后wireshark无法获取网络接口
    ASIO库使用注意事项
    使用gdb添加断点的几种方式
    select、poll、epoll的比较
    CMakeLists.txt编写常用命令
    Ubuntu下使用linuxdeployqt打包Qt程序
  • 原文地址:https://www.cnblogs.com/purpleraintear/p/6486169.html
Copyright © 2011-2022 走看看