版權聲明:本文由賀嘉 原創文章,轉載請註明出處:
文章原文連接:https://www.qcloud.com/community/article/431172001487671163json
來源:騰雲閣 https://www.qcloud.com/community小程序
如何用Baas快速在騰訊雲上開發小程序-系列4:實現客戶側商品列表、商品詳情頁程序微信
1、實驗簡介
經過實現商品列表、商品詳情頁程序,熟練掌握雲端數據表查詢操做。session
2、實驗目標微信開發
3、實驗步驟
3.1 Hello Worldapp
應用設置
第一步: 修改 app.js ,初始化全局對象dom
第二步: 修改 app.json 添加頁面清單,修改標題欄默認屬性xss
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. width: 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. width: 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="width:88rpx;"> 3. <image mode="widthFix" src="/res/icons/shop.png"></image> 4. </view> 5. <view style="width:40%"> 6. <text style="padding-left:20rpx;"> {{cart.total}} 件商品 {{cart.show _price}} 元 </text> 7. </view> 8. <view class="text-right" style="width: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="width:200rpx;" class="push-r-10"> <image bindtap="detail" data-id="{{item._id}}" mode="widthFix" src="{{item. corver}}"></image> </view> 5. <view style="width:50%" class="push-r-10"><text bindtap="de tail" data-id="{{item._id}}" class="font-s15">{{item.name}}</text> </view> 6. <view style="width: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="width:30%;min-width: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. width: 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. width: 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. },
4、實驗結果 經過本實驗,熟練掌握小程序調試方法;熟悉數據表查詢操做。