小程序中是很強調組件中開發的,我們看到的頁面是由許多組件組成的,但是這些組件是如何組合在一起的呢?來學習一下!
一、組件中數據的獲取
接着上一篇文章,繼續來優化代碼,如何把從服務器上獲取的數據顯示到組件的頁面中?
(1)繼續優化代碼
創建models文件夾,來將classic.js中的代碼繼續分離出來,來創建一個classicModel類
進一步進行代碼的抽離,代碼如下:
1 // models文件夾下classic.js代碼如下 2 import { 3 HTTP 4 } from '../util/http.js'; 5 6 // 新建ClassicModel類來從服務器獲取數據 7 class ClassicModel extends HTTP { 8 getLatest(sCallBack) { 9 this.request({ 10 url: 'classic/latest', 11 success: (res) => { 12 //調用回調函數 來傳遞數據 13 sCallBack(res); 14 } 15 }) 16 } 17 } 18 // 一定不要忘記 export ClassicModel 19 export { 20 ClassicModel 21 } 22 23 // classic文件夾下classic.js文件中代碼如下,很簡潔,還利於維護 24 // 這里導入的時候需要寫成相對路徑 25 import { 26 ClassicModel 27 } from '../../models/classic.js'; 28 29 // 實例化HTTP類 30 var classic = new ClassicModel(); 31 32 /** 33 * 生命周期函數--監聽頁面加載 34 */ 35 onLoad: function(options) { 36 classic.getLatest((res) => { 37 this.setData({ 38 classic: res 39 }) 40 }) 41 },
來看一下頁面中調用組件的時候如何將數據傳遞到組件中:
classic文件夾中classic.wxml頁面中調用組件的時候。可以把數據存放到組件的屬性中,利用數據綁定來傳遞數據

2、組件代碼的開發
index.wxml、index.wxss、index.js文件的代碼:
// index.wxml代碼 <view class='classic-container'> <!--大圖暫時用的圖片路徑是死的--> <image class='classic-img' src='images/《飲食男女》@2x.png'/> <image class='tag' src='images/movie@tag.png' /> <text class='content'>{{content}}</text> </view> // index.wxss代碼 .classic-container{ display: flex; flex-direction: column; align-items: center; } .classic-img{ width:750rpx; height: 500rpx; } .tag{ width: 46rpx; height: 142rpx; position: relative; right: 310rpx; bottom: 58rpx; } .content{ font-size: 36rpx; max-width: 550rpx; } // index.js代碼 主要是設置了兩個屬性值 大圖路徑以及文字內容 /** * 組件的屬性列表 */ properties: { img:{ type:String }, content:String },
3、組件在classic頁面中使用
需要在classic.json中引入組件。並且在classic.wxml頁面中使用組件標簽,加入完成之后就OK了!
1 // classic.json中代碼 2 { 3 "usingComponents": { 4 "v-like":"/components/like/index", 5 "v-movie": "/components/classic/movie/index" 6 } 7 } 8 9 // classic.wxml文件中加入組件標簽 10 <v-movie img='{{classic.image}}' content='{{classic.content}}' />
我咋感覺對於老師來說,這些都是信手捏來,很簡單,對我來說,難的要死的感覺,加油吧,向前沖!
三、自定義事件
這個主要是在點贊功能的上面進行的進一步的完善的功能,我們是如何將點贊的狀態發送給服務端的,在這里最好的解決辦法是在組件中進行自定義事件的開發,學習一下自定義事件的開發
代碼如下:
1 // like組件的index.js中寫代碼 2 /** 3 * 組件的方法列表 4 */ 5 methods: { 6 onLike:function(event){ 7 var like = this.properties.like; 8 var count = this.properties.count; 9 10 count = like?count-1:count+1; 11 this.setData({ 12 count:count, 13 like:!like 14 }) 15 // 激活一個自定義事件 16 var behaiver = this.properties.like?'like':'cancel'; 17 this.triggerEvent('like',{ 18 behaiver:behaiver 19 },{}); 20 } 21 } 22 23 // 組件的調用方classic中來監聽組件中自定義的事件 bind后面是自定義組件的名稱 24 <v-like bind:like='onLike' like='{{classic.like_status}}' count='{{classic.fav_nums}}' /> 25 26 // 在classic中的classic.js中來實現處理邏輯 27 // 監聽like組件的自定義的like事件 28 onLike: function(event) { 29 console.log(event); 30 },
完善這個自定義組件中的監聽事件的代碼:
新建like.js 文件在modules文件夾下面,這個文件主要是創建LikeModel,將數據的更新方法寫到這個model中,使得代碼更好維護,模塊化更加清楚
代碼如下:models文件夾下的like.js文件中的代碼
1 import { 2 HTTP 3 } from '../util/http.js'; 4 5 6 // 創建LikeModel繼承HTTP類 7 class LikeModel extends HTTP { 8 like(behavior, artId, category) { 9 var url = behavior == 'like' ? 'like' : 'like/cancel' 10 this.request({ 11 url: url, 12 type: 'POST', 13 data: { 14 art_id: artId, 15 type: category 16 } 17 }) 18 } 19 } 20 21 // 這個是不能忘記的 22 export { 23 LikeModel 24 }
LIkeModel在classic文件夾下的classic.js中的使用:這個就是講參數傳遞到LIkeModel中的方法中去:
1 // 這里導入的時候需要寫成相對路徑 2 import { 3 ClassicModel 4 } from '../../models/classic.js'; 5 import { 6 LikeModel 7 } from '../../models/like.js'; 8 9 // 實例化HTTP類 10 var classicModel = new ClassicModel(); 11 var likeModel = new LikeModel(); 12 13 Page({ 14 15 /** 16 * 頁面的初始數據 17 */ 18 data: { 19 classic: null 20 }, 21 22 // 監聽like組件的自定義的like事件 23 onLike: function(event) { 24 console.log(event); 25 var behaiver = event.detail.behaiver; 26 likeModel.like(behaiver, this.data.classic.id, this.data.classic.type); 27 }, 28 29 })
四、期刊組件的開發
基本上照着這個樣式來開發這個組件,這個其實可以分為兩部分的,期刊號和發行日期,這個期刊號是需要接口中獲得的,需要定義成屬性,來開發這個組件吧
1、首選創建組件component所需文件,先創建epsoide文件夾,再在該文件夾下面創建組件
2、改造js文件,創建屬性與內部數據,這里涉及到了組件的聲明周期函數,這個在官網上地址:
https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/lifetimes.html
1 // components/epsoide/index.js 2 Component({ 3 /** 4 * 組件的屬性列表 屬性中的變量不能和data中的變量同名 5 */ 6 properties: { 7 index: { 8 // index屬性 顯示要求 如果是個位數 需要顯示兩位 例如 '08' '18' 9 type: Number, 10 observer: function(newVal, oldVal, changedPath) { 11 // console.log(newVal); 12 // console.log(oldVal); 13 // console.log(changedPath); 14 // 不要在observer函數中改變屬性的值,有可能造成無限循環調用,因為observer監聽的是當屬性改變的時候觸發的事件,在這里設置屬性值,當屬性值改變時,還會繼續調用 15 var value = newVal < 10 ? '0' + newVal : newVal; 16 this.setData({ 17 _index: value 18 }) 19 } 20 } 21 }, 22 23 /** 24 * 組件的初始數據 25 */ 26 data: { 27 // data中數據的賦值,不能像properties中那樣,直接給初始值就行 28 months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], 29 year: 0, 30 month: '', 31 _index: '' 32 }, 33 34 // 組件生命周期函數attached 在組件實例進入頁面節點樹時執行 35 attached: function() { 36 // console.log(this.properties); 37 // console.log(this.data); 38 var date = new Date(); 39 var year = date.getFullYear(); 40 var month = date.getMonth(); 41 42 // 將值綁定到data中的變量上 43 this.setData({ 44 year: year, 45 month: this.data.months[month] 46 }) 47 }, 48 49 /** 50 * 組件的方法列表 51 */ 52 methods: { 53 54 } 55 })
3、創建頁面以及css樣式
//index.wxml 中代碼如下 <view class='container'> <view class='index-container'> <text class='plain'>No.</text> <text class='index'>{{_index}}</text> <view class='line'></view> </view> <view class='date-container'> <text class='month'>{{month}}</text> <text class='year'>{{year}}</text> </view> </view> // index.wxss樣式文件代碼 這個我是真的一點都不會 .container { height: 60rpx; display: inline-flex; flex-direction: row; } .index-container { display: flex; flex-direction: row; align-items: baseline; } .plain { font-size: 32rpx; } .index { font-size: 60rpx; line-height: 60rpx; font-weight: 800; margin-right: 14rpx; } .line { height: 44rpx; margin-right: 14rpx; border-left: 1px solid black; } .date-container { display: flex; flex-direction: column; margin-top: 5rpx; } .month { font-size: 24rpx; line-height: 24rpx; } .year { font-size: 20rpx; }
4、頁面中的classic中的使用
// classic.json 中引入組件 { "usingComponents": { "v-like":"/components/like/index", "v-movie": "/components/classic/movie/index", "v-epsoide": "/components/epsoide/index" } } // classic.wxml中顯示組件 <v-epsoide index='{{classic.index}}' />