邊做邊學入門微信小程序之仿豆瓣評分


微信小程序由於適用性強、邏輯簡要、開發迅速的特性,疊加具有海量活躍用戶的騰訊公司背景,逐漸成為了輕量級單一功能應用場景的較佳承載方式,諸如電影購票、外賣點餐、移動商城、生活服務等場景服務提供商迅速切入了。

為了貼合實際的應用情況,本篇以豆瓣評分小程序為參考樣例,邊做邊學小程序的入門開發知識。

目錄

效果圖
Demo源碼
開發環境
了解官方樣例
開發者工具
樣例源碼結構
開發實戰
底部Tab卡頁
分析開發需求
評分條模板
rpx長度單位
數據綁定
條件渲染
列表渲染
電影海報模板
模板的使用
區塊模板
主頁
網絡請求
邏輯實現
setData
點擊事件
詳情頁
更多頁
擴展知識
思考題

效果圖

先看一下對比效果圖,共三個頁面,分別為首頁、更多頁和詳情頁,左側為豆瓣評分官方小程序,右側為仿作。因API數據問題,沒有做搜索功能。

主頁

 

imgimg

 

更多頁

 

imgimg

 

詳情頁

 

imgimg

 

Demo源碼

本篇完整源碼已提交在: https://github.com/cnwen/wechatapp_movie

開發環境

調試基礎庫:1.9.91(2018.03.07)

微信開發者工具:Windows版v1.02.1802270

了解官方樣例

打開微信開發者工具,新建一個小程序項目。

1.選擇項目代碼存放的目錄;

2.填入你的小程序AppID(若無AppID請點擊“注冊”獲取,也可選擇“體驗小程序”,如需真機預覽須有AppID);

3.勾選“建立普通快速啟動模板”。

點擊“確定”按鈕后,開發者工具將為我們建立一個簡單的小程序模板,我們可以通過這個樣例來建立對開發者工具和小程序的初步認識。

imgimg

 

開發者工具

我們觀察開發者工具,發現由三個主要區域構成,分別是模擬器、編輯器和調試器。

 

imgimg

 

模擬器:頂端含有三個下拉列表,可以配置模擬的機型和所處的網絡環境。

編輯器:分為源碼目錄區域和代碼區域。

調試器:頂端含有控制台、網絡、存儲等選項卡頁。

樣例源碼結構

根目錄含有pages、utils文件夾和三個名稱為app的文件。顧名思義,pages正是存放小程序各個頁面的文件夾,一些公共的工具類建議放在utils文件夾,app文件是小程序的全局文件。

點擊查看app.json文件的源碼,可以看到含有pages和window兩個鍵值對。

 

imgimg

 

pages負責配置小程序的頁面,里面有2條路徑,分別對應index和logs頁面。

Tips:1.第一條路徑固定為小程序的首頁,如果把logs路徑放到首位,那么logs頁面是首頁;2.同一個頁面的js/wxml/wxss文件的名稱必須相同,因為路徑是以文件名稱來識別的,路徑是“pages/index/index”,注意后面不帶js/wxml/wxss等后綴,系統會在該路徑尋找需要格式文件;3.需要顯示的獨立頁面都需要在此處配置,template模板文件則不需要。

window負責全局的窗口配置,如導航欄背景色、導航欄文字等。你可以修改它們的值,保存后在模擬器上看到效果。

試試將navigationBarBackgroundColor的值改為#ffae00,將navigationBarTitleText的值改為“電影排行榜”,按Ctrl+S鍵保存看看模擬器中的效果吧。

Tips:1.backgroundTextStyle的值目前只有兩種:light和dark;2.navigationBarTextStyle的值目前只有兩種:black和white。

回到源碼目錄,對比index和logs頁面的構成,發現index頁面並沒有.json文件,可見這個文件並非是必須的。但是,如果有這個文件,那么必然不能為空,否則控制台會報錯,可在里面寫入一個大括號{}保存即可。

開發實戰

官方樣例先認識到這里,我們對開發者工具和小程序源碼構成有了一個初步的印象后,開始邊做邊學。

底部Tab卡頁

我們使用鼠標右鍵將源碼目錄pages下的index/logs兩個文件夾刪除,並打開app.json,在pages的值中配置下圖中的兩條路徑。

 

imgimg

 

按Ctrl+S鍵保存,開發者工具將自動在指定路徑為我們創建兩個頁面,如下圖所示。

imgimg

 

此時,模擬器中的首頁已經變成了movies目錄下的index頁面,因為我們剛才把這個頁面的路徑配置在app.json文件中pages值的首位了。

imgimg

 

如果我們要查看mine頁面怎么辦呢?除了使用后文將提到的頁面跳轉功能,這里用Tab卡頁的切換功能來試試。在app.json文件中添加tabBar內容,如下所示。

{
"pages":[
"pages/movies/index",
"pages/mine/mine"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#ffae00",
"navigationBarTitleText": "電影排行榜",
"navigationBarTextStyle":"white"
},
"tabBar": {
"list": [
{
"pagePath": "pages/movies/index",
"text": "電影"
},
{
"pagePath": "pages/mine/mine",
"text": "我的"
}
],
"borderStyle": "black",
"selectedColor": "#ffae00"
}
}

模擬器預覽效果如下圖:

imgimg

 

在list的值中,我們配置了2個卡頁,text是卡頁的文字,pathPath代表了頁面路徑,當點擊卡頁時,將跳轉到指定路徑的頁面。注意卡頁數必須為2-5個才合規,否則控制台會報錯。並且,這里的路徑必須被包含在頂端的pages值中,因為所有可抵達頁面都必須在pages中配置路徑。

紅色箭頭指向處有一條水平灰色線,這是卡頁和內容頁的分界線,由borderStyle屬性控制,其值默認為black,目前暫時只有black和white值可選。

selectedColor表示卡頁選中時,其文字的顏色,用十六進制表示。另外卡頁背景色也可配置。

選項卡可以含有圖標,配置方法如下:

{
"pagePath": "pages/movies/index",
"text": "電影",
"iconPath": "images/tabbar/movie.png",
"selectedIconPath": "images/tabbar/movieSelected.png"
}

 

imgimgimgimg

 

一個為默認圖標,一個是選中時顯示的圖標。(請看圖標路徑,我在左側目錄樹的根目錄新建了images/tabbar目錄,並放入了4張圖標,圖標資源在Github源碼中有)

這樣,首頁Tab便完成了。接下來我們來分析頁面結構,並實現一些公用的template模板文件。

分析開發需求

作為編碼者,在開始編碼之前,我們要養成先從整體層面上分析整體需求的好習慣,有利於后續的代碼編寫及維護。

 

imgimg

 

觀察首頁、更多頁和電影詳情頁,可以很容易地歸納出一些可以共用的頁面元素:1.首頁由三大塊組成,正在熱映、即將上映和排行榜區塊除了數據不同,頁面結構是相同的(即紅色框,后文我用block區塊模板代指這塊);2.每個block模板中含有若干個海報模板,由電影海報、電影名稱和評分條、評分數組成(藍色框,后文稱poster海報模板);3.每個評分條是由5顆星星組成的(粉紅框,后文稱ratingbar評分條模板)。

評分條模板

模板頁面(template)是官方提供的一種實現頁面元素復用、減少重復工作的良好實現形式。

從上面的分析中,我們發現這里提到的三個模板是層層嵌套的,因此,作為入門學習者,我們先從最內層的模板開始實現,即先實現評分條ratingbar模板文件。

 

imgimg

 

評分星星有三種狀態,我們在images目錄中新建ratingbar目錄,並將這三個星星圖標放入。(Github源碼中含有本文所需的所有素材)

 

imgimg

 

在movies目錄右鍵鼠標,依次新建名為ratingbar的目錄和Page。打開app.json文件,我們發現開發者工具自動在pages值為我們配置了ratingbar頁面的路徑。

 

imgimg

 

作為模板文件,是在其它頁面中導入使用的,它不會單獨被使用,因此其實它不需要在app.json的pages值中配置路徑,並且該頁面只需wxml和wxss即可,js和json文件都是用不上的,它所含的頁面元素的數據和行為都是由引用它的頁面來操縱的,后文會對此有所涉及。

但在此時,我們需要在模擬器中調試、查看其效果,所以要將它當作單獨頁面來使用一次,調試完后可將js/json文件刪除,並刪除在app.json中pages值中的路徑,此是后話,暫且略過。

我們在app.json中將ratingbar頁面路徑移到pages值的首位(見上圖),保存后發現模擬器的首頁變成了ratingbar頁面。

 

imgimg

 

頁面上唯一的一條內容是由開發者工具在新建頁面時自動生成的。我們打開ratingbar.wxml頁面,將自動生成的標簽內容刪除,並輸入以下內容,按Shift+Alt+F鍵格式化代碼:

<!--pages/movies/ratingbar/ratingbar.wxml-->
<view class='ratingbar-stars'>
<!--全黃星星-->
<image src='/images/ratingbar/star_fill_whole.png'/>
<image src='/images/ratingbar/star_fill_whole.png'/>
<image src='../../../images/ratingbar/star_fill_whole.png'/>
<!--半黃半灰星星-->
<image src='/images/ratingbar/star_fill_half.png'/>
<!--全灰星星-->
<image src='../../../images/ratingbar/star_fill_none.png'/>
</view>

可以視為官方提供的一種容器,需要成對出現的,在這里它內部含有5個image組件。class表示其樣式,它將會去同頁面的wxss文件中查找並渲染值為.ratingbar-stars的樣式(見下文)。image是圖像組件,有一個屬性src,表示要顯示的圖片的地址。像這類內容不需要再包含其它控件的控件,你也可以寫成單閉合標簽的形式。

這里src的路徑出現了2種寫法,絕對路徑和相對路徑,如果不了解的可另外拓展一下,這里的路徑是一樣的。

再點開ratingbar.wxss文件,並輸入以下內容:

/* pages/movies/ratingbar/ratingbar.wxss */
/* class="ratingbar-stars"的控件的樣式 */
.ratingbar-stars {
display: flex;
flex-direction: row;
padding-right: 4rpx;
}
/* class="ratingbar-stars"的控件下所包含的image控件的樣式 */
.ratingbar-stars image {
height: 17rpx;
width: 17rpx;
padding-top: 5rpx;
padding-right: 4rpx;
}

這里的首個.ratingbar-stars樣式(請注意樣式名前面有個小點號“.”),與的class相呼應,將會用於渲染該控件。

這里采用了CSS中著名的flex彈性盒子模型,flex-direction:row;意味着其內部控件將采用水平橫向的方式排列,要表示豎直排列可將值改為column。

第二個.ratingbar-stars image樣式(請注意中間有空格,且image前面沒有點號),表示渲染class='ratingbar-stars'的控件內部包含的image控件,這里表示了高height、寬width、距離頂部的內邊距padding-top、距離右側的內邊距padding-right。CSS的更多屬性知識歡迎另行拓展,這是一個多記多練才能生巧的知識。

rpx長度單位

rpx是微信小程序推出的單位,可以根據不同手機不同的屏幕寬度進行內容自適應,使頁面元素在不同屏幕寬度的手機上看起來具有一致性。

無論手機屏幕實際寬度是多少,小程序都會在底層將屏幕寬度換算成750份,如果設計師以iphone6的750*1334(物理像素)為標准出設計稿的話,1rpx=0.5px=1物理像素,你可以直接使用設計師標注的參數加上rpx即可。

上面的width:17rpx表示無論在什么樣的移動設備上,其大小都為750份中的17份,寬屏則顯示大一些,窄屏則顯示小一些,視覺效果一致。

按Ctrl+S鍵保存現有代碼,模擬器即時顯示出了目前的頁面效果:3顆黃星、1顆半星、1顆灰星。

 

imgimg

 

在wxml文件中,我們在內寫了5個靜態的image圖像控件。然而在實際場景中,這個不可能是寫死的,而應該是根據電影的不同評分進行相應的顯示。

動態數據涉及到一些數據綁定等相關的知識,這里先簡要介紹一下。

數據綁定

{{}}

WXML 中的動態數據均來自對應 Page 的 data,數據綁定使用 Mustache 語法(雙大括號)將變量包起來,如:

<view wx:for="{{count}}">
<text>{{stars}}</text>
</view>

頁面渲染時,系統將去對應頁面的js文件的data屬性中尋找count和stars變量。

條件渲染

wx:if

在框架中,使用 wx:if="{{條件語句}}" 來判斷是否需要渲染該代碼塊:

<image wx:if="{{stars>30}}" src='/images/ratingbar/star_fill_whole.png' />

上條語句表示當滿足stars>30的條件時,渲染image控件。

除了if條件外,還有wx:elif 和 wx:else語句:

<image wx:if="{{stars>30}}" src='/images/ratingbar/star_fill_whole.png' />
<image wx:elif="{{stars>20}}" src='/images/ratingbar/star_fill_half.png' />
<image wx:else src='/images/ratingbar/star_fill_none.png' />

wx:if 有且只有一個;

wx:elif 是else if的意思,可以有多個;

wx:else 最多只有一個。

系統按順序判斷各個條件,遇到成立的條件時則渲染該控件,其余控件則不會渲染。

注意:內部的條件語句的結果為{{false}}才表示條件不成立,不帶{{}}的值將會被視為文本從而判定為條件成立。

<view wx:if="{{false}}"/> <!--條件不成立-->
<view wx:if="false"/> <!--條件成立-->
<view wx:if="3"/> <!--條件成立-->
列表渲染

wx:for

在組件上使用 wx:for 控制屬性綁定一個數組,即可使用數組中各項的數據重復渲染該組件。數組長度為多少,就會重復渲染多少次。

<block wx:for="{{count}}">
<text>{{index}}:{{item}}</text>
</block>

在循環時,當前項的變量名默認為 item,其下標變量名默認為 index。

<block wx:for="{{count1}}">
<block wx:for="{{count2}}">
<text>{{index}}:{{item}}</text>
</block>
</block>

如果遇到這種多重循環呢,如何在內部表示不同數組的當前項和下標呢?

可以用wx:for-item和wx:for-index分別指定當前項的變量名和下標的變量名:

<block wx:for="{{count1}}" wx:for-item="outer" wx:for-index="i">
<block wx:for="{{count2}}" wx:for-item="inner" wx:for-index="j">
<text>{{i}}:{{outer}}</text>
<text>{{j}}:{{inner}}</text>
</block>
</block>

數據綁定相關的知識大致了解了,我們打開ratingbar.js,並在data內定義兩個變量:

// pages/movies/ratingbar/ratingbar.js
Page({
data: {
count:[3,5,6,8,9],
stars:16
}
})

然后將ratingbar.wxml文件內容修改為:

<!--pages/movies/ratingbar/ratingbar.wxml-->
<view class='ratingbar-stars'>
<!--count數組長度為5,共5次循環顯示5顆星星-->
<block wx:for="{{count}}">
<!--全黃星星-->
<image wx:if="{{stars/10>=index+1}}" src='/images/ratingbar/star_fill_whole.png' />
<!--半黃半灰星星-->
<image wx:elif="{{stars/10>=index && stars%10!=0}}" src='/images/ratingbar/star_fill_half.png' />
<!--全灰星星-->
<image wx:else src='/images/ratingbar/star_fill_none.png' />
</block>
</view>

按Ctrl+S保存看看模擬器的效果,把stars的值改為其它數(0-50之間)試試看星星的顯示效果吧。Tips:這里的條件語句是研究豆瓣電影API里電影評分的規律得來的。它的stars取值為0/5/10……40/45/50。

據我們之前對豆瓣評分小程序的分析,評分條一般作為一個元素在相關頁面中顯示,不會獨立作為頁面來顯示。小程序官方提供了機制來解決這種復用性的問題,代碼片段一處編寫,多處使用,極大地精簡了代碼的臃腫,也令程序員有更多精力專注於必要的地方。其結構如下:

<template name="模板名稱">
<!--這里是要復用的代碼片段-->
</template>

我們將剛才編寫的ratingbar.wxml代碼最外層加上模板標識:

<!--pages/movies/ratingbar/ratingbar.wxml-->
<template name="template-ratingbar-stars">
<view class='ratingbar-stars'>
<!--數組長度為5,共5次循環顯示5顆星星-->
<block wx:for="{{[3,5,6,8,9]}}">
<!--全黃星星-->
<image wx:if="{{stars/10>=index+1}}" src='/images/ratingbar/star_fill_whole.png' />
<!--半黃半灰星星-->
<image wx:elif="{{stars/10>=index && stars%10!=0}}" src='/images/ratingbar/star_fill_half.png' />
<!--全灰星星-->
<image wx:else src='/images/ratingbar/star_fill_none.png' />
</block>
</view>
</template>

模板名稱是template-ratingbar-stars,在其它頁面引入本模板后,根據該名稱即可找到此模板。因為評分條有且只有5顆星星,所以這里將count的值直接寫在此處wx:for="{{[3,5,6,8,9]}}",然后我們把ratingbar.js中的相關值注釋掉:

Page({
data: {
// count:[3,5,6,8,9],
// stars:16
}
})

因為作為模板,將在多處調用,其所使用的值(如這里的stars)將由調用的地方傳入,也正因為這樣,才有復用性可言。其實,模板文件只有wxml和wxss有用,js和json文件刪除亦可。

電影海報模板

接下來,我們來編寫電影海報,就是藍框這個:

imgimg有多處使用了這樣的結構,顯然,也應當是一個模板文件。

 

我們可以參照編寫評分條模板的步驟,先將其當作為一個頁面,配置在小程序的首頁,在js中模擬數據,調試成功后,再改成模板頁面。

首先,在movies目錄下新建poster目錄和poster頁面,在app.json的pages屬性中,將poster頁面路徑放在首位(ratingbar路徑可以刪除),以便在模擬器中查看效果和調試。

{
"pages": [
"pages/movies/poster/poster",
"pages/movies/ratingbar/ratingbar",
"pages/movies/index",
"pages/mine/mine"
],
……
}

在poster.js中寫入一些模擬數據:

// pages/movies/poster/poster.js
Page({
data: {
title: "奇跡男孩 Wonder",
images: {
large: "https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2507709428.jpg"
},
rating: {
average: 8.6,
max: 10,
min: 0,
stars: "45"
}
}
})

我們將在頁面中通過綁定數據來獲取這些數據,如電影名稱{{title}}、海報圖片{{images.large}}、電影評分{{rating.average}}等。

在poster.wxss中寫入:

/* 導入評分條模板wxss文件,注意是@import */
@import "../ratingbar/ratingbar.wxss";
.movie {
display: flex;
flex-direction: column;
padding-right: 12rpx;
}
.poster {
width: 200rpx;
height: 270rpx;
padding-bottom: 10rpx;
}
.movie-name {
color: #333333;
font-size: 24rpx;
line-height: 24rpx;
margin: 10rpx 0 5rpx 0;
}
.ratingbar {
display: flex;
flex-direction: row;
}
.ratingbar-score{
color: #999999;
font-size: 20rpx;
}
模板的使用

這里用到了評分條模板,因此在開頭導入了評分條模板的wxss樣式。每個.樣式都對應着下文相關控件的class。

在poster.wxml中寫入:

<!--導入評分條模板wxml文件,注意別少了后面的 / 符號-->
<import src="../ratingbar/ratingbar.wxml" />
<view class='movie' catchtap='catchTapMovie' data-movieid='{{id}}'>
<!--海報圖-->
<image class="poster" src='{{images.large}}'></image>
<!--電影名稱-->
<text class='movie-name'>{{title}}</text>
<!--評分星星和數字-->
<view class='ratingbar'>
<!--評分條-->
<template is="template-ratingbar-stars" data="{{...rating}}" />
<!--評分分數-->
<text class='ratingbar-score'>{{rating.average}}</text>
</view>
</view>

同理,開頭也導入了評分條模板的wxml文件,並通過以下方式使用。

<!--評分條-->
<template is="template-ratingbar-stars" data="{{...rating}}" />

is屬性值正是評分條模板的name名稱,data值將相關數據傳入評分條模板。

poster.js的data屬性中含有rating數據,其格式見下文。上文中的…rating即是將rating數據散開,將其內容傳入評分條模板,評分條模板里可以直接使用{{stars}},而不需要通過{{rating.stars}}的方式。

rating: {
average: 8.6,
max: 10,
min: 0,
stars: "45"
}

這里還出現了諸如下文的屬性名,我們將留到后面講解。

<view class='movie' catchtap='catchTapMovie' data-movieid='{{id}}'>

現在,將poster.js的data屬性中的模擬數據注釋或刪除掉,並將poster.wxml封裝成模版,如下文所示。

<!--導入評分條模板wxml文件,注意別少了后面的 / 符號-->
<import src="../ratingbar/ratingbar.wxml" />
<!--封裝成名稱為template-poster的模板-->
<template name="template-poster">
<view class='movie' catchtap='catchTapMovie' data-movieid='{{id}}'>
<!--海報圖-->
<image class="poster" src='{{images.large}}'></image>
<!--電影名稱-->
<text class='movie-name'>{{title}}</text>
<!--評分星星和數字-->
<view class='ratingbar'>
<!--評分條-->
<template is="template-ratingbar-stars" data="{{...rating}}" />
<!--評分分數-->
<text class='ratingbar-score'>{{rating.average}}</text>
</view>
</view>
</template>

區塊模板

有了電影海報模板后,接下來我們進行下一步。觀察到首頁是由三個結構一模一樣的紅色區塊組成,顯然,這也可以是一個模板,暫且稱之為block吧。

 

imgimg

 

步驟和先前個模板一樣,為節省篇幅,這里會更簡略地以貼代碼為主。首頁在movies目錄下新建block目錄和頁面,並在app.json文件的pages中將block頁面的路徑移到首位,以便觀察模擬器效果。

在images目錄新建block目錄,放入下面這張名為arrow-right.png的右箭頭圖片。

imgimg

 

在block.js文件的data屬性中寫入模擬的數據(如下),有兩個鍵值對,一為blockTitle區塊標題,一為blockMovies為區塊電影數據(與豆瓣API返回的格式一致,有刪減字段,但結構不變)。

// pages/movies/block/block.js
Page({
data: {
blockTitle:"正在熱映",
blockMovies: {
"count": 4,
"start": 0,
"subjects": [{
"casts": [{
"avatars": {
"large": "https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1509423054.09.jpg"
},
"name": "阿德瓦·香登"
},
{
"avatars": {
"large": "https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p13628.jpg"
},
"name": "阿米爾·汗"
},
{
"avatars": {
"large": "https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1494080264.12.jpg"
},
"name": "塞伊拉·沃西"
}
],
"comments_count": 5951,
"countries": [
"印度"
],
"directors": [{
"avatars": {
"large": null
},
"name": "阿德瓦·香登"
}],
"genres": [
"劇情",
"音樂"
],
"id": 259,
"images": {
"large": "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2508925590.jpg"
},
"original_title": "神秘巨星 Secret Superstar",
"rating": {
"average": 8.2,
"max": 10,
"min": 0,
"stars": "40"
},
"reviews_count": 292,
"summary": "14歲的印度少女尹希婭(塞伊拉·沃西 飾)熱愛唱歌,因父親阻撓,她只能蒙面拍攝並上傳自彈自唱原創歌曲的視頻,孰料憑借天籟歌喉在網上一炮而紅,備受爭議的音樂人夏克提·庫馬爾(阿米爾·汗 飾)也向她拋出橄欖枝,尹希婭的生活發生了翻天覆地的變化……",
"title": "神秘巨星 Secret Superstar",
"warning": "數據來源於網絡整理,僅供學習,禁止他用。如有侵權請聯系公眾號:小樓昨夜又秋風。我將及時刪除。",
"wish_count": 22447,
"year": 2017
},
{
"casts": [{
"avatars": {
"large": "https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p19485.jpg"
},
"name": "李芳芳"
},
{
"avatars": {
"large": "https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1359895311.0.jpg"
},
"name": "章子怡"
},
{
"avatars": {
"large": "https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1472787652.32.jpg"
},
"name": "黃曉明"
}
],
"comments_count": 58027,
"countries": [
"中國大陸"
],
"directors": [{
"avatars": {
"large": null
},
"name": "李芳芳"
}],
"genres": [
"劇情",
"愛情",
"戰爭"
],
"id": 265,
"images": {
"large": "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2507572275.jpg"
},
"original_title": "無問西東",
"rating": {
"average": 7.5,
"max": 10,
"min": 0,
"stars": "40"
},
"reviews_count": 4354,
"summary": "如果提前了解了你所要面對的人生,你是否還會有勇氣前來?吳嶺瀾、沈光耀、王敏佳、陳鵬、張果果,幾個年輕人滿懷諸多渴望,在四個非同凡響的時空中一路前行。\\n吳嶺瀾(陳楚生 飾),出發時意氣風發,卻很快在途中迷失了方向。沈光耀(王力宏 飾),自願參與了最殘酷的戰爭,他一直在努力去做那些令他害怕,但重要的事。王敏佳(章子怡 飾)最初的錯誤,只是為了虛榮撒了一個小謊;最初的煩惱,只是在兩個優秀的男人中選擇一個。但命運,卻把她拖入被眾人唾罵的深淵。陳鵬(黃曉明 飾)把愛情擺在了理想前面,但愛情卻沒有把他擺在前面。他說,“我有人要照顧”,縱然這意味着與所有人作對,意味着要和她一起被放逐千里。張果果(張震 飾),身處爾虞我詐的職場,“贏”是他的習慣。為了贏,他總是見招拆招,先發制人。而有一天,他卻面臨了一個比“贏”更重要的選擇。這幾個年輕人,在最好的年紀迎來了最殘酷的...",
"title": "無問西東",
"warning": "數據來源於網絡整理,僅供學習,禁止他用。如有侵權請聯系公眾號:小樓昨夜又秋風。我將及時刪除。",
"wish_count": 32890,
"year": 2018
},
{
"casts": [{
"avatars": {
"large": "https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p57551.jpg"
},
"name": "斯蒂芬·卓博斯基"
},
{
"avatars": {
"large": "https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1456737567.18.jpg"
},
"name": "雅各布·特倫布萊"
},
{
"avatars": {
"large": "https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p8889.jpg"
},
"name": "朱莉婭·羅伯茨"
}
],
"comments_count": 4854,
"countries": [
"美國"
],
"directors": [{
"avatars": {
"large": null
},
"name": "斯蒂芬·卓博斯基"
}],
"genres": [
"劇情",
"家庭",
"兒童"
],
"id": 269,
"images": {
"large": "https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2507709428.jpg"
},
"original_title": "奇跡男孩 Wonder",
"rating": {
"average": 8.6,
"max": 10,
"min": 0,
"stars": "45"
},
"reviews_count": 162,
"summary": "電影《奇跡男孩》改編自全球暢銷小說《奇跡》,講述了一個溫暖千萬家庭的成長故事。10 歲的奧吉(雅各布·特倫布萊 Jacob Tremblay 飾)天生臉部畸形,此前一直在家中和媽媽(朱莉婭·羅伯茨 Julia Roberts 飾)自學。當他小學五年級時,奧吉進入父母為他精心挑選的學校上學。在這里,奧吉將與校長、老師以及性格迥異的同學相處,他不尋常的外表讓他成為同學們討論的焦點,並終日受到嘲笑和排斥,就連好不容易交到的新朋友也似乎不太值得信任。幸運的是,在成長過程中,奧吉的父母、姐姐一直是他最堅強的后盾,在他們的支持與關愛下,奧吉憑借自身的勇氣、善良、聰敏影響激勵了許多身邊的人,並收獲了友誼、尊重與愛,最終成長為大家心目中的不可思議的“奇跡”。",
"title": "奇跡男孩 Wonder",
"warning": "數據來源於網絡整理,僅供學習,禁止他用。如有侵權請聯系公眾號:小樓昨夜又秋風。我將及時刪除。",
"wish_count": 29417,
"year": 2017
},
{
"casts": [{
"avatars": {
"large": "https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20143.jpg"
},
"name": "丁晟"
},
{
"avatars": {
"large": "https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1509429399.29.jpg"
},
"name": "王凱"
},
{
"avatars": {
"large": "https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1422629943.25.jpg"
},
"name": "馬天宇"
}
],
"comments_count": 6927,
"countries": [
"中國大陸",
"香港"
],
"directors": [{
"avatars": {
"large": null
},
"name": "丁晟"
}],
"genres": [
"劇情",
"動作"
],
"id": 260,
"images": {
"large": "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2508615612.jpg"
},
"original_title": "英雄本色2018",
"rating": {
"average": 5.2,
"max": 10,
"min": 0,
"stars": "25"
},
"reviews_count": 711,
"summary": "周凱(王凱 飾)參與走私,被身為緝毒警察的弟弟周超(馬天宇 飾)逮捕入獄。三年后,周凱出獄,改過自新。曾經的手下阿倉(余皚磊 飾)已為毒販頭目,為獲取周凱的海外客戶資料,設計加害周凱。江湖中的好兄弟馬柯(王大陸 飾)為了替周凱報仇,失去一條腿。自己的親弟弟周超不相信哥哥周凱已金盆洗手,不斷搜集證據,欲親手逮捕周凱。最終,周凱與警方合作,逮捕了阿倉,兩兄弟重歸於好。",
"title": "英雄本色2018",
"warning": "數據來源於網絡整理,僅供學習,禁止他用。如有侵權請聯系公眾號:小樓昨夜又秋風。我將及時刪除。",
"wish_count": 4552,
"year": 2018
}
]
}
}
})

在block.wxss文件中寫入以下數據:

/* pages/movies/block/block.wxss */
/* 導入電影海報模板的WXSS */
@import "../poster/poster.wxss";
.block-title-bar {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 30rpx 20rpx 0rpx 20rpx;
}
.block-title {
color: #333333;
font-size: 30rpx;
}
.block-more {
display: flex;
flex-direction: row;
align-items: center;
}
.block-more-text {
color: #ffae00;
font-size: 24rpx;
}
.block-more-icon {
width: 12rpx;
height: 20rpx;
padding-left: 6rpx;
}
.block-scroll-view {
display: flex;
flex-direction: row;
}
.block-movie-row{
display: flex;
flex-direction: row;
padding: 20rpx 0 20rpx 20rpx;
}
.block-movie-card {
display: flex;
flex-direction: row;
margin-right: 10rpx;
}

在block.wxml中寫入:

<!--pages/movies/block/block.wxml-->
<!--導入電影海報模板-->
<import src="../poster/poster.wxml" />
<view>
<!--區塊頂欄-->
<view class='block-title-bar'>
<!--類別標題,如正在熱映-->
<text class='block-title'>{{blockTitle}}</text>
<view class='block-more' catchtap='catchMore' data-title='{{blockTitle}}'>
<!--更多-->
<text class='block-more-text'>更多</text>
<!--右箭頭-->
<image class='block-more-icon' src='/images/block/arrow-right.png'></image>
</view>
</view>
<!--電影海報展示條-->
<scroll-view scroll-x="{{true}}" class='block-scroll-view'>
<view class='block-movie-row'>
<block wx:for="{{blockMovies.subjects}}" wx:for-item="poster">
<!--單個電影海報-->
<view class='block-movie-card'>
<template is="template-poster" data="{{...poster}}" />
</view>
</block>
</view>
</scroll-view>
</view>

按Ctrl+S保存后,模擬器效果如下。第一個出現了電影名稱過長的情形,我們后續會寫一個stringUtil.js的工具類來截斷。

 

imgimg

 

我們在block頁面導入了poster模板的wxml和wxss文件,並通過下文代碼使用了。

<!--導入電影海報模板-->
<import src="../poster/poster.wxml" />
……
<!--電影海報展示條-->
<scroll-view scroll-x="{{true}}" class='block-scroll-view'>
<view class='block-movie-row'>
<block wx:for="{{blockMovies.subjects}}" wx:for-item="poster">
<!--單個電影海報-->
<view class='block-movie-card'>
<template is="template-poster" data="{{...poster}}" />
</view>
</block>
</view>
</scroll-view>
……

這里使用了一個新的控件滑動條,有scroll-x和scroll-y屬性,用以設定滑動的方向是水平還是豎直。

在滑動條內部,通過wx:for循環取出blockMovies.subjects的值,用poster表示當前項。

電影海報通過海報模板導入,通過{{…poster}}的形式散開poster的值傳入海報模板中,為海報模板中的同名變量提供對應的值。

<!--類別標題,如正在熱映-->
<text class='block-title'>{{blockTitle}}</text>
<view class='block-more' catchtap='catchMore' data-title='{{blockTitle}}'>

在上文中又出現了catchtap和data-形式的屬性名,這是界面上“更多”按鈕的點擊事件和自定義屬性,后文詳細講解。

最后將block.js中data里的相關數據注釋或刪除,並在block.wxml里封裝模板。

<!--導入電影海報模板-->
<import src="../poster/poster.wxml" />
<!--封裝成區塊模板-->
<template name="template-block">
<view>
……
</view>
</template>

別忘了在app.json文件的data屬性中將主頁的路徑“pages/movies/index”提到首位,我們即將要編寫主頁了。

到目前為止,我們所需要的三個模板已經全部封裝完了。

block模板里導入了poster模板,后者又嵌入了ratingbar模板,極大的精簡了相關的代碼,加強了代碼的易維護性。不信?看主頁,我們只需寥寥數行代碼即可。

下篇:https://mp.weixin.qq.com/s/Isfk9s2cgtyXdh5Olap9QA


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM