這個主要是來開發book的這個大模塊的,看看如何優雅的開發出booked模塊!html
1、book模塊的建立json
這個就很簡單了,建立一個大的框架是很簡單的小程序
2、組件的編寫微信小程序
(1)wxml組件頁面的編碼promise
首先是將一本書的展現看作是一個組件,而後就是循環展現全部請求的書籍的信息,因此須要把一本書當作一個組件來製做,這樣就能比較合理的解決這個問題!服務器
1 // book組件的頁面的代碼 2 <view class="container"> 3 <image src="{{book.image}}"></image> 4 <view class="description"> 5 <text class="title">{{book.title}}</text> 6 <text class="author">{{book.author}}</text> 7 <view class="foot"> 8 <text class="footer">{{book.fav_nums}} 喜歡</text> 9 </view> 10 </view> 11 </view>
將這個book組件引用到page中去,給用戶展現書籍的信息,須要在book.json 中引入,而且將組件的寫到book.wxml頁面代碼中,這裏暫時只是展現一個book組件微信
1 // page中的book.json 中引入book組件 2 { 3 "usingComponents": { 4 "v-book":"/components/book/index" 5 } 6 } 7 8 // page中的book.wxml中引入v-book標籤 9 <v-book book="{{books[0]}}" /> 10 11 // page中的book.js中操做數據,將數據傳遞到頁面屬性中,只寫主要的生命週期函數 12 import { 13 BookModel 14 } from '../../models/book.js'; 15 16 // 實例化BookModel對象 17 const bookModel = new BookModel(); 18 19 Page({ 20 21 /** 22 * 頁面的初始數據 23 */ 24 data: { 25 // 服務器請求的數據 book的集合 26 books:[] 27 }, 28 29 /** 30 * 生命週期函數--監聽頁面加載 31 */ 32 onLoad: function(options) { 33 // 這種寫法才能規避回調地獄的 34 bookModel.getHotList() 35 .then(res => { 36 // 這種寫法不完善 只是作了賦值 頁面沒法獲取到 37 // this.data.books = res 38 this.setData({ 39 books:res 40 }) 41 }) 42 43 },
(2)book組件樣式的編碼框架
這個啊,讓人頭疼的,我是寫不出來,哈哈xss
1 .container{ 2 margin-top: 30rpx; 3 display: flex; 4 position: relative; 5 box-shadow: 2px 2px 3px #e3e3e3; 6 flex-direction: column; 7 width: 240rpx; 8 height: 360rpx; 9 } 10 11 /* 書籍封面的樣式 */ 12 .container image { 13 width: 100%; 14 height: 100%; 15 border-radius: 2px; 16 } 17 18 .description{ 19 width: 216rpx; 20 position: absolute; 21 bottom: 0; 22 background-color: #fff; 23 padding: 5rpx 10rpx 8rpx 15rpx; 24 font-size: 24rpx; 25 display: flex; 26 flex-direction: column; 27 border-bottom-left-radius: 2px; 28 border-bottom-right-radius: 2px; 29 } 30 31 .title{ 32 margin-top: 10rpx; 33 text-overflow: ellipsis; 34 white-space: nowrap; 35 overflow: hidden; 36 } 37 38 .author{ 39 font-size: 20rpx; 40 color: #999999; 41 margin-bottom: 10rpx; 42 text-overflow: ellipsis; 43 white-space: nowrap; 44 overflow: hidden; 45 } 46 47 .foot{ 48 font-size: 20rpx; 49 display: flex; 50 flex-direction: row; 51 justify-content: flex-end; 52 } 53 54 .footer{ 55 color: 56 }
3、組件的應用函數
由於書籍是使用的一組的書籍組件,如何來把服務器上傳回來的全部的書籍信息所有顯示出來,這個就是咱們須要考慮的,須要完成的
小程序中確定是存在相似for循環的,那就是wx:for 可是在小程序中並非叫作for循環,而是叫作列表渲染
(1)列表渲染
1 <block wx:for="{{books}}"> 2 <v-book book="{{item}}" /> 3 </block>
(2)總體頁面佈局
這個就是pages中的book頁面的代碼了,主題包含一個搜索欄,以及下面的圖書列表
1 <view class="container"> 2 <view class="header"> 3 <view class="box"> 4 <image src="/images/icon/search.png"></image> 5 <text>搜索書籍</text> 6 </view> 7 </view> 8 <view class="sub-container"> 9 <image src="/images/book/quality.png" class="head-img"></image> 10 <view class="books-container"> 11 <block wx:for="{{books}}"> 12 <v-book book="{{item}}" /> 13 </block> 14 </view> 15 </view> 16 </view>
(3)總體的樣式代碼
看一下如何設計樣式來讓這個頁面看起來那麼舒服,這是最難的吧,充分靈活的使用flex佈局來實現這樣的樣式
1 .container{ 2 display: flex; 3 flex-direction: column; 4 align-items: center; 5 width:100%; 6 } 7 8 .sub-container{ 9 display: flex; 10 flex-direction: column; 11 align-items: center; 12 background-color: #f5f5f5; 13 margin-top:100rpx; 14 /* z-index:0; */ 15 } 16 17 .books-container{ 18 margin-top:10rpx; 19 display: flex; 20 flex-direction: row; 21 flex-wrap: wrap; 22 padding: 0 90rpx 0 90rpx; 23 justify-content: space-between; 24 } 25 26 .books-container v-book{ 27 margin-bottom: 30rpx; 28 } 29 30 .box{ 31 display:flex; 32 flex-direction: row; 33 justify-content: center; 34 align-items: center; 35 border-radius: 50px; 36 background-color: #f5f5f5; 37 height: 34px; 38 width:700rpx; 39 color:#999999; 40 } 41 42 .header{ 43 /* fixed 是使得容器固定 */ 44 position: fixed; 45 background-color: #ffffff; 46 height:100rpx; 47 width:100%; 48 border-top:1px solid #f5f5f5; 49 border-bottom:1px solid #f5f5f5; 50 display: flex; 51 flex-direction: row; 52 align-items: center; 53 justify-content: center; 54 box-shadow:0 0 3px 0 #e3e3e3; 55 z-index: 99; 56 } 57 58 .head-img{ 59 width:106rpx; 60 height:34rpx; 61 margin-top:40rpx; 62 } 63 64 .box image{ 65 margin-right:10px; 66 width:14px; 67 height:14px; 68 margin-bottom:-2px; 69 }
4、book組件中業務邏輯的實現
這個主要是實現功能就是從book列表頁面用戶直接點擊以後,跳轉到書籍的詳細信息的頁面,這個該如何實現,是在組件中實現跳轉邏輯,仍是在頁面上實現,如何取捨,如何選擇,是選擇組件的通用性呢?仍是選擇組件的設計實現簡單呢?如何來寫這個邏輯代碼?
一、不考慮組件的通用性
不考慮組件通用性的話,就直接在組件中實現頁面的跳轉就OK了,具體的實現代碼以下:
1 // 組件中的wxml文件 2 <view bind:tap="onTap" class="container"> 3 </view> 4 5 // 組件中的js文件 小程序中的navigateTo實現跳轉 6 methods: { 7 onTap(event){ 8 const bid = this.properties.book.id; 9 wx.navigateTo({ 10 url: `/pages/book-detail/book-detail?bid=${bid}`, 11 }) 12 } 13 }
二、考慮組件通用性的
5、book詳細信息的開發
一、小程序中的編譯模式
爲了方便開發,讓小程序每次編譯以後都會是書籍詳細信息的頁面,咱們能夠添加編譯模式,來控制編譯以後的啓動頁面,這樣有利於提升開發效率:
選擇本身定義的編譯模式:
二、具體book詳情頁面的開發
首先把詳情頁面的樣式也頁面的代碼進行編寫,這裏就是沒有按照順序來整理出來代碼,直接把完整的代碼都拿出來吧
首先是詳情頁面的wxml文件中靜態頁面代碼:(這裏不是完整的,下面的點評功能沒有實現)
1 <wxs src="../../util/filter.wxs" module="util"/> 2 <view class="container"> 3 <!-- 頭部信息 --> 4 <view class="head"> 5 <image src="{{book.image}}"></image> 6 <text class="title">{{book.title}}</text> 7 <text class="author">{{book.author}}</text> 8 </view> 9 <!-- 短評 --> 10 <view class="sub-container"> 11 <text class="headline">短評</text> 12 <view class="comment-container"> 13 <block wx:for="{{util.limit(comments,10)}}" wx:key=""> 14 <v-tag tag-class="{{index==0?'ex-tag1':'' || index==1?'ex-tag2':''}}" text="{{item.content}}"> 15 <text class="num" slot="after">{{"+" + item.nums}}</text> 16 </v-tag> 17 </block> 18 </view> 19 <!-- 內容簡介 --> 20 <view class="sub-container"> 21 <text class="heading">內容簡介</text> 22 <text class="content" decode="{{true}}">{{util.format(book.summary)}}</text> 23 </view> 24 </view> 25 <!-- 書籍出版信息 --> 26 <view class="sub-container"> 27 <text class="heading">書籍信息</text> 28 <view class="detail-container"> 29 <view class="vertical description"> 30 <text>出版社</text> 31 <text>出版年</text> 32 <text>頁數</text> 33 <text>訂價</text> 34 <text>裝幀</text> 35 </view> 36 <view class="vertical"> 37 <text>{{book.publisher}}</text> 38 <text>{{book.pubdate}}</text> 39 <text>{{book.pages}}</text> 40 <text>{{book.price}}</text> 41 <text>{{book.binding}}</text> 42 </view> 43 </view> 44 </view> 45 </view>·
接下來是wxss樣式的代碼:
1 .container { 2 background-color: #f5f5f5; 3 width: 100%; 4 } 5 6 .head { 7 background-color: #fff; 8 padding-top: 40rpx; 9 padding-bottom: 40rpx; 10 display: flex; 11 flex-direction: column; 12 align-items: center; 13 } 14 15 .title { 16 color: #2f2f2f; 17 margin-top: 20rpx; 18 font-size: 38rpx; 19 font-weight: 600; 20 } 21 22 .author { 23 font-size: 28rpx; 24 color: #999; 25 } 26 27 .head image { 28 width: 200rpx; 29 height: 300rpx; 30 box-shadow: 2px 2px 3px #e3e3e3; 31 } 32 33 .sub-container { 34 width: 690rpx; 35 display: flex; 36 flex-direction: column; 37 align-items: center; 38 margin-top: 30rpx; 39 background-color: #fff; 40 padding: 30rpx; 41 } 42 43 .headline { 44 font-size: 30rpx; 45 font-weight: 600; 46 color: #2f2f2f; 47 margin-bottom: 20rpx; 48 } 49 50 .comment-container { 51 display: flex; 52 flex-direction: row; 53 flex-wrap: wrap; 54 } 55 56 .comment-container v-tag { 57 margin-right: 15rpx; 58 margin-bottom: 10rpx; 59 } 60 61 .num { 62 margin-left: 10rpx; 63 font-size: 22rpx; 64 color: #aaa; 65 } 66 67 .content{ 68 text-indent: 58rpx; 69 font-weight: 500 70 } 71 72 /* 給標籤前兩個設置背景色 這種設置違背了組件的封裝原則的*/ 73 74 /* 這裏引入了小程序中的externalClasses來進行自定義組件的樣式的設置 */ 75 76 /* .comment-container > v-tag:nth-child(1) > view{ 77 background-color: #fffbdd; 78 } 79 80 .comment-container > v-tag:nth-child(2) > view{ 81 background-color: #eefbff; 82 } */ 83 84 /* !important 強制提升外部樣式的權限 */ 85 86 .ex-tag1 { 87 background-color: #fffbdd !important; 88 } 89 90 .ex-tag2 { 91 background-color: #eefbff !important; 92 } 93 94 /* 書籍出版信息樣式 */ 95 .detail-container{ 96 width: 100%; 97 display: flex; 98 flex-direction: row; 99 justify-content: flex-start; 100 margin-bottom: 100rpx; 101 font-size: 28rpx; 102 color: #666; 103 } 104 105 .vertical{ 106 display: flex; 107 flex-direction: column; 108 } 109 110 .description{ 111 color: #999; 112 margin-right: 30rpx; 113 }
最後是book詳情頁面的js代碼:
1 import { 2 BookModel 3 } from '../../models/book.js'; 4 5 // 實例化BookModel對象 6 const bookModel = new BookModel(); 7 8 Page({ 9 10 /** 11 * 頁面的初始數據 12 */ 13 data: { 14 comments:[], 15 book:null, 16 likeStatus:false, 17 likeCount:0 18 }, 19 20 /** 21 * 生命週期函數--監聽頁面加載 22 */ 23 onLoad: function (options) { 24 // 從外部頁面傳遞過來的參數id 25 const bid = options.bid; 26 console.log(bid); 27 const detail = bookModel.getDetail(bid); 28 const comments = bookModel.getComments(bid); 29 const likeStatus = bookModel.getLikeStatus(bid); 30 31 // 利用promise的then的回調獲取數據 32 detail.then(res => { 33 // console.log(res); 34 this.setData({ 35 book:res 36 }) 37 }) 38 39 comments.then(res => { 40 // console.log(res); 41 this.setData({ 42 comments:res.comments 43 }) 44 }) 45 46 likeStatus.then(res =>{ 47 // console.log(res); 48 this.setData({ 49 likeStatus:res.like_status, 50 likeCount:res.fav_nums 51 }) 52 }) 53 54 },
三、小程序插槽slot
這裏的插槽很適合來作自定義組件的,這種用法非誠靈活,感受真的有一種美妙的感受-slot的官方介紹:
其實文檔中已經寫的很清楚了,可是仍是看一下老師的講解,畢竟在實戰中引用纔是最重要的,如何將理論的東西應用到實戰中,是很值得思考的東西
1 <view class="container"> 2 <slot name="before"></slot> 3 <text>{{text}}</text> 4 <!-- 微信小程序中的 插槽 slot --> 5 <slot name="after"></slot> 6 </view>
這個其實就至關於佔位符,我事先在這裏佔有一個位置,隨時等待有人來佔有這個地方,可是若是沒人來佔,對整體的佈局也不會產生影響,有人的話,我就要把這我的給大家展現出來了,這我的就和組件中的其餘的標籤融爲一體了,注意這裏須要指定slot的name值,由於在page中是須要根據name值來找具體哪一個slot的
看page中如何插入到插槽中slot的:
1 <view class="sub-container"> 2 <text class="headline">短評</text> 3 <view class="comment-container"> 4 <block wx:for="{{comments}}" wx:key=""> 5 <v-tag text="{{item.content}}"> 6 <text class="num" slot="after">{{"+" + item.nums}}</text> 7 </v-tag> 8 </block> 9 </view>
這裏是將text標籤插入到插槽中,那麼插槽中就會被一個text標籤徹底的佔有了,你看到就是text標籤中的內容了
可是,這樣的話,slot並不會生效,須要在配置一個參數,就是:
1 options: { 2 multipleSlots:true 3 },
這樣的話,才能實現slot的功能
四、小程序中的externalClasses
這個是說的是小程序中的自定義組件如何來引入外部樣式類,就是如何將page中的樣式放入到自定義組件中,使其生效,小程序提供了externalClasses這個配置,能夠應用這個設置來解決這個問題
小程序中國的官方的介紹文檔:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html#外部樣式類
仍是來看一下這個東西是如何在實戰中應用的:
首先,看自定義組件中須要設置哪些地方:
1 // 首先是須要設置 js中配置 2 externalClasses:[ 3 'tag-class' 4 ], 5 6 // 其次是須要在頁面中使用這個自定義class 7 <!-- tag標籤組件 短評以及搜索中的標籤組件 --> 8 <view class="container tag-class"> 9 <slot name="before"></slot> 10 <text>{{text}}</text> 11 <!-- 微信小程序中的 插槽 slot --> 12 <slot name="after"></slot> 13 </view>
這樣的話,咱們就能夠在使用自定義標籤的時候來傳遞樣式進去了
1 // 這裏面有一個樣式的切換 第一個和第二個分別展現不一樣的背景色 2 <view class="sub-container"> 3 <text class="headline">短評</text> 4 <view class="comment-container"> 5 <block wx:for="{{comments}}" wx:key=""> 6 <v-tag tag-class="{{index==0?'ex-tag1':'' || index==1?'ex-tag2':''}}" text="{{item.content}}"> 7 <text class="num" slot="after">{{"+" + item.nums}}</text> 8 </v-tag> 9 </block> 10 </view>
再來看一下ex-tag1與ex-tag2的樣式設置
1 .ex-tag1 { 2 background-color: #fffbdd !important; 3 } 4 5 .ex-tag2 { 6 background-color: #eefbff !important; 7 }
注意:!important 這裏是提升該樣式的重要性的,若是沒有的話,雖然外部樣式已經設置進去了,可是可能會被默認的樣式覆蓋的,這裏爲了強制覆蓋默認樣式而進行的設置
五、小程序中的wxs
這個文件的主要功能就是在wxml文件中能夠調用外部的js代碼,固然js代碼是放在wxs文件中的,看看這個新的知識點是如何來實現的,官方文檔:
https://developers.weixin.qq.com/miniprogram/dev/reference/wxs/01wxs-module.html
開始編寫邏輯代碼:
1 // filter.wxs文件中代碼 注意model.exports導出 var關鍵字 正則替換寫法 2 var format = function(text){ 3 if(!text){ 4 return 5 } 6 var reg = getRegExp('\\\\n','g'); 7 return text.replace(reg,'\n '); 8 9 } 10 11 module.exports = { 12 format:format 13 } 14 15 // 頁面中的引入代碼 16 <wxs src="../../util/filter.wxs" module="util"/> 17 // 標籤中使用 18 <text class="content" decode="{{true}}">{{util.format(book.summary)}}</text>