您好,登錄后才能下訂單哦!
筆記內(nèi)容:構(gòu)建新聞詳情頁面
筆記日期:2018-01-09
在編寫從文章列表跳轉(zhuǎn)到新聞詳情頁的代碼之前,先來修改一下之前的頁面,之前我們編寫了兩個(gè)模板文件,但是還有兩個(gè)細(xì)節(jié)沒有完善好,一個(gè)是post.wxss中的.post-container樣式?jīng)]有移植到模板文件中,另一個(gè)是wxml模板文件中每句數(shù)據(jù)綁定代碼都需要通過item這個(gè)子元素去調(diào)用屬性,顯得有點(diǎn)麻煩,我們可以使用一種語法去解決這個(gè)問題。
1.首先將post.wxss中的.post-container樣式移植到模板文件中
2.解決item重復(fù)的問題,在post.wxml中將之前的 template 代碼修改為以下內(nèi)容:
<template is="postItem" data="{{...item}}" />
然后模板文件中的數(shù)據(jù)綁定代碼就不需要重復(fù)使用item子元素進(jìn)行屬性的調(diào)用了:
<!-- 模板文件需要使用template標(biāo)簽包圍 -->
<template name="postItem">
<view class='post-container'>
<view class='post-author-date'>
<image src='{{avatar}}' class='post-author'></image>
<text class="post-date">{{date}}</text>
</view>
<text class='post-title'>{{title}}</text>
<image class='post-image' src='{{imgSrc}}'></image>
<text class='post-content'>{{content}}</text>
<view class='post-like'>
<image src='../../images/icon/chat.png' class='post-like-img'></image>
<text class='post-like-font'>{{reading}}</text>
<image src='../../images/icon/view.png' class='post-like-img'></image>
<text class='post-like-font'>{{collection}}</text>
</view>
</view>
</template>
完成以上的修改后,就可以開始編寫新聞詳情頁的代碼了:
1.構(gòu)建目錄文件結(jié)構(gòu):
2.由于我們需要實(shí)現(xiàn)點(diǎn)擊一個(gè)文章列表中的文章就跳轉(zhuǎn)到該文章的詳情頁面,所以我們還得給每一個(gè)文章做一個(gè)標(biāo)識符,不然誰知道你點(diǎn)的是哪篇文章。這個(gè)標(biāo)識符可以寫在數(shù)據(jù)文件中,作為一個(gè)屬性存在,所以需要在數(shù)據(jù)文件中為每一個(gè)文章數(shù)據(jù)都加上一個(gè)屬性,我定義的屬性名稱是postId:
// 將數(shù)據(jù)整合成數(shù)組類型
var local_database = [
{
date: "Jan 06 2018",
title: "正是蝦肥蟹壯時(shí)",
imgSrc: "/images/post/crab.png",
avatar: "/images/avatar/1.png",
content: "“山明水凈夜來霜,數(shù)樹深紅出淺黃。試上高樓清入骨,豈如春色嗾人狂?!苯鹎飼r(shí)節(jié),天高云淡,秋風(fēng)送爽,氣候宜人。秋風(fēng)秋陽中,碩果墜掛枝頭,玉米撫須含笑,高粱引頸高歌,豆莢飽滿圓潤。",
reading: "112",
collection: "96",
postId:0,
},
{
date: "Jan 03 2018",
title: "比利·林恩的中場戰(zhàn)事",
imgSrc: "/images/post/bl.png",
avatar: "/images/avatar/2.png",
content: "伊拉克戰(zhàn)爭時(shí)期,來自美國德州的19歲技術(shù)兵比利·林恩(喬·阿爾文 Joe Alwyn 飾)因?yàn)橐欢闻既慌臄z的視頻而家喻戶曉。那是一次規(guī)模不大卻激烈非常的遭遇戰(zhàn),戰(zhàn)斗中林恩所在的B班班長(范·迪塞爾 Vin Diesel 飾)遭到當(dāng)?shù)匚溲b分子的伏擊和劫持,而林恩為了營救班長不惜鋌而走險(xiǎn)沖鋒陷陣。",
reading: "92",
collection: "65",
postId: 1,
},
{
date: "Jan 05 2018",
title: "肖申克的救贖",
imgSrc: "/images/post/xs.jpg",
avatar: "/images/avatar/3.png",
content: "20世紀(jì)40年代末,小有成就的青年銀行家安迪(蒂姆·羅賓斯 Tim Robbins 飾)因涉嫌殺害妻子及她的情人而鋃鐺入獄。在這座名為肖申克的監(jiān)獄內(nèi),希望似乎虛無縹緲,終身監(jiān)禁的懲罰無疑注定了安迪接下來灰暗絕望的人生。",
reading: "92",
collection: "65",
postId: 2,
},
{
date: "Jan 01 2018",
title: "霸王別姬",
imgSrc: "/images/post/bj.jpg",
avatar: "/images/avatar/4.png",
content: "段小樓(張豐毅)與程蝶衣(張國榮)是一對打小一起長大的師兄弟,兩人一個(gè)演生,一個(gè)飾旦,一向配合天衣無縫,尤其一出《霸王別姬》,更是譽(yù)滿京城,為此,兩人約定合演一輩子《霸王別姬》。但兩人對戲劇與人生關(guān)系的理解有本質(zhì)不同,段小樓深知戲非人生,程蝶衣則是人戲不分。",
reading: "92",
collection: "65",
postId: 3,
},
{
date: "Jan 08 2018",
title: "這個(gè)殺手不太冷",
imgSrc: "/images/post/ss.jpg",
avatar: "/images/avatar/5.png",
content: "里昂(讓·雷諾飾)是名孤獨(dú)的×××,受人雇傭。一天,鄰居家小姑娘馬蒂爾達(dá)(納塔麗·波特曼飾)敲開他的房門,要求在他那里暫避殺身之禍。原來鄰居家的主人是警方緝毒組的眼線,只因貪污了一小包×××而遭惡警(加里·奧德曼飾)殺害全家的懲罰。",
reading: "92",
collection: "65",
postId: 4,
},
{
date: "Jan 04 2018",
title: "阿甘正傳",
imgSrc: "/images/post/ag.jpg",
avatar: "/images/avatar/1.png",
content: "阿甘(湯姆·漢克斯 飾)于二戰(zhàn)結(jié)束后不久出生在美國南方阿拉巴馬州一個(gè)閉塞的小鎮(zhèn),他先天弱智,智商只有75,然而他的媽媽是一個(gè)性格堅(jiān)強(qiáng)的女性,她常常鼓勵(lì)阿甘“傻人有傻?!保詮?qiáng)不息。",
reading: "92",
collection: "65",
postId: 5,
},
]
// 設(shè)置一個(gè)數(shù)據(jù)出口
module.exports = {
// 輸出的是一個(gè)Array對象
postList: local_database,
}
3.在post.wxml文件中增加一個(gè)view標(biāo)簽,把template標(biāo)簽包圍起來,因?yàn)閠emplate標(biāo)簽只是相當(dāng)于一個(gè)占位符,編譯之后這個(gè)標(biāo)簽是不存在的。然后給這個(gè)view標(biāo)簽注冊一個(gè)tap事件,并且自定義一個(gè)屬性進(jìn)行postId的數(shù)據(jù)綁定:
<!-- 自定義屬性必須以 data- 為前綴,后面連接的單詞可以自定義 -->
<view catchtap="onPostTap" data-postId="{{item.postId}}">
<template is="postItem" data="{{...item}}"/>
</view>
4.然后到post.js文件中增加一個(gè)事件函數(shù):
onPostTap: function(event){
// 從事件源中獲取postId數(shù)據(jù)
var postId = event.currentTarget.dataset.postid;
console.log("on post id is " + postId);
},
event是事件源對象,是默認(rèn)會傳入的參數(shù),currentTarget是當(dāng)前被觸發(fā)事件的目標(biāo)對象,dataset是數(shù)據(jù)集對象,數(shù)據(jù)要從數(shù)據(jù)集對象中獲取。至于為什么是通過postid獲取數(shù)據(jù)而不是通過data-postId或者postId獲取,請參考下圖:
如圖,可以看到,自定義屬性被編譯之后的名稱并不是原本的名稱,所以我們通過dataset數(shù)據(jù)集對象獲取自定義屬性的數(shù)據(jù)時(shí)需要以編譯后的名稱為準(zhǔn)。
5.接著就可以開始實(shí)現(xiàn)頁面跳轉(zhuǎn)了,先在post-detail.wxml中編寫一段話:
<text>
這是文章詳情頁面
</text>
然后再app.json中加上一段post-detail的信息配置,每當(dāng)我們新增頁面都需要如此進(jìn)行配置:
"pages/posts/post-detail/post-detail"
回到post.js中,編寫頁面跳轉(zhuǎn)代碼:
onPostTap: function(event){
// 從事件源中獲取postId數(shù)據(jù)
var postId = event.currentTarget.dataset.postid;
wx.navigateTo({
url: 'post-detail/post-detail',
})
},
完成以上操作編譯之后現(xiàn)在點(diǎn)擊文章列表中的文章就可以跳轉(zhuǎn)到文章詳情頁面了:
編寫post-detail.wxml代碼:
<view class='container'>
<image src='/images/post/sls.jpg' class='head-iamge'></image>
<image class='audio' src='/images/music/music-start.png'></image>
<view class='author-date'>
<image src='/images/avatar/2.png' class='avatar' ></image>
<text class='author'>zero</text>
<text class='const-text'>發(fā)表于</text>
<text class='date'>3天前</text>
</view>
<text class='title'>審美的進(jìn)化機(jī)制</text>
<view class='tool'>
<view class='circle-img'>
<image src='/images/icon/collection.png'></image>
<image class='share-img' src='/images/icon/share.png'></image>
</view>
<view class='horizon'></view>
</view>
<text class='detail'>2017年讀的書中,有一本書是《紐約時(shí)報(bào)》年度十佳(2017 Ten Best Books),即:《美的進(jìn)化——達(dá)爾文被遺忘的擇偶理論如何塑造動物世界乃至我們》(The Evolution of Beauty: How Darwin’s Forgotten Theory of Mate Choice Shapes the Animal World — and Us)。時(shí)報(bào)網(wǎng)站刊登了英文版評介的譯文:如果一本科學(xué)書籍能做到有顛覆性,倡導(dǎo)女權(quán)主義,還能改變我們看待自己身體的方式,但同時(shí)主要還是關(guān)于鳥類的,那就是這本書了。普魯姆是一位鳥類學(xué)家,他為達(dá)爾文的另一個(gè)基本上被忽略了的雌雄淘汰理論進(jìn)行了辯護(hù)。</text>
</view>
post-detail.wxss代碼:
.container {
display: flex;
flex-direction: column;
}
.head-iamge {
width: 750rpx;
height: 460rpx;
}
.author-date {
flex-direction: row;
margin-left: 30rpx;
margin-top: 20rpx;
}
.avatar {
height: 64rpx;
width: 64rpx;
vertical-align: middle;
}
.author {
font-size: 30rpx;
font-weight: 300;
margin-left: 20rpx;
vertical-align: middle;
color: #666;
}
.const-text {
font-size: 24rpx;
color: #999;
margin-left: 20rpx;
}
.date {
font-size: 24rpx;
margin-left: 30rpx;
color: #999;
vertical-align: middle;
}
.title {
margin-left: 40rpx;
font-size: 36rpx;
font-weight: 700;
margin-top: 30rpx;
letter-spacing: 2px;
color: #4b556c;
}
.tool {
margin-top: 20rpx;
}
.circle-img {
float: right;
margin-right: 40rpx;
vertical-align: middle;
}
.circle-img image{
width: 90rpx;
height: 90rpx;
}
.share-img {
margin-left: 30rpx;
}
.horizon {
width: 660rpx;
height: 1px;
background-color: #e5e5e5;
vertical-align: middle;
position: relative;
top: 46rpx;
margin: 0 auto;
z-index: -99;
}
.detail{
color: #666;
margin-left: 30rpx;
margin-top: 20rpx;
margin-right: 30rpx;
line-height: 44rpx;
letter-spacing: 2px;
}
.audio{
width: 102rpx;
height: 110rpx;
position: absolute;
left: 50%;
margin-left: -51rpx;
top: 180rpx;
opacity: 0.6; // 設(shè)置透明度為0.6
}
app.wxss代碼:
text{
font-family: MicroSoft Yahei;
font-size: 24rpx;
}
完成效果:
上面把基本的靜態(tài)頁面做完了,但是導(dǎo)航欄顏色還不太對,而且少了個(gè)標(biāo)識文字,所以現(xiàn)在就來把這個(gè)位置的樣式完善好。
app.json文件內(nèi)容:
{
"pages": [
"pages/welcome/welcome",
"pages/posts/post",
"pages/posts/post-detail/post-detail"
],
"window": {
"navigationBarBackgroundColor": "#405f80"
}
}
welcome.json文件內(nèi)容:
{
"navigationBarBackgroundColor": "#b3d4db"
}
post.json文件內(nèi)容:
{
"navigationBarTitleText": "文與字"
}
post-detail.json文件內(nèi)容:
{
"navigationBarTitleText": "閱讀"
}
完成效果:
首先是postId的獲得,因?yàn)椴煌膒ostId需要輸出不同的文章詳情數(shù)據(jù):
1.在post.js的navigateTo方法的url參數(shù)中,加上一個(gè)id參數(shù):
onPostTap: function(event){
// 從事件源中獲取postId數(shù)據(jù)
var postId = event.currentTarget.dataset.postid;
//console.log("on post id is " + postId);
wx.navigateTo({
url: 'post-detail/post-detail?id=' + postId, // 通過url傳遞postId
})
},
2.然后在post-detail.js中,寫一個(gè)onLoad函數(shù)把id獲得到手:
Page({
onLoad:function(option){
var postId = option.id; // 這里的id對應(yīng)的是url參數(shù)上的id
console.log(postId);
}
})
3.編譯之后,點(diǎn)擊不同的文章,看看控制臺中是否有輸出相應(yīng)的postId,有輸出的話就證明獲得成功。
完成以上操作后,就可以把新聞詳情頁面的數(shù)據(jù)放進(jìn)數(shù)據(jù)文件中,然后進(jìn)行數(shù)據(jù)綁定:
post-data.js文件內(nèi)容:
// 將數(shù)據(jù)整合成數(shù)組類型
var local_database = [
{
date: "Jan 06 2018",
title: "正是蝦肥蟹壯時(shí)",
imgSrc: "/images/post/crab.png",
avatar: "/images/avatar/1.png",
content: "“山明水凈夜來霜,數(shù)樹深紅出淺黃。試上高樓清入骨,豈如春色嗾人狂?!苯鹎飼r(shí)節(jié),天高云淡,秋風(fēng)送爽,氣候宜人。秋風(fēng)秋陽中,碩果墜掛枝頭,玉米撫須含笑,高粱引頸高歌,豆莢飽滿圓潤。",
reading: "112",
collection: "96",
headImgSrc: "/images/post/crab.png",
author: "zero",
dataTime:"24小時(shí)前",
detail: "“山明水凈夜來霜,數(shù)樹深紅出淺黃。試上高樓清入骨,豈如春色嗾人狂?!苯鹎飼r(shí)節(jié),天高云淡,秋風(fēng)送爽,氣候宜人。秋風(fēng)秋陽中,碩果墜掛枝頭,玉米撫須含笑,高粱引頸高歌,豆莢飽滿圓潤。棉桃鼓脹欲裂,水稻灌漿初熟,世間萬物經(jīng)過春的孕育,夏的生長,即將抵達(dá)收獲的季節(jié)。在這瓜果飄香、稻黍起舞的召喚聲中,又是一度蟹肥蝦壯時(shí)。地處黃海之濱的小城,在秋風(fēng)的撫慰、秋陽的光照下,瞬間也喧囂起來。任意走進(jìn)城中的每一個(gè)菜市場,在顯眼的位置上,沖入耳際的是此起彼伏的吆喝聲,映入眼簾的是那些小商小販們搶占有利地勢將一只只塑料箱一字排開的情景。淺箱中,健壯的對蝦、竹節(jié)蝦在水中跳躍,舒展著彎曲的身體;深箱中,一貫橫行霸道的螃蟹擁擠在狹小的空間里,相互肆意踐踏,有些不甘蝸居的螃蟹,順著筆直的箱壁艱難地攀爬著,雖經(jīng)百般努力,終以失敗而告終。那些聚集在網(wǎng)兜里的螃蟹,更是不甘寂寞,身體被束縛著無法動彈,便利用可以自由呼吸的嘴巴,于窸窸窣窣中不停地吐著一串串泡沫,以示抗議,也以此證明自己是個(gè)活物。特別是那些個(gè)頭較大的螃蟹,仿佛知道自己的身價(jià)不菲,為此,更是氣宇軒昂,自以為是。也許,它們是得到垂青和恩寵的一類吧,受到了特別的眷顧,活動的空間相對較大,所以也更加肆無忌憚。只要有人試圖靠近,便會舉著那兩只肥碩的大螯向你示威,仿佛在警告你:別碰我,否則休怪我無禮!",
postId: 0,
},
{
date: "Jan 03 2018",
title: "比利·林恩的中場戰(zhàn)事",
imgSrc: "/images/post/bl.png",
avatar: "/images/avatar/2.png",
content: "伊拉克戰(zhàn)爭時(shí)期,來自美國德州的19歲技術(shù)兵比利·林恩(喬·阿爾文 Joe Alwyn 飾)因?yàn)橐欢闻既慌臄z的視頻而家喻戶曉。那是一次規(guī)模不大卻激烈非常的遭遇戰(zhàn),戰(zhàn)斗中林恩所在的B班班長(范·迪塞爾 Vin Diesel 飾)遭到當(dāng)?shù)匚溲b分子的伏擊和劫持,而林恩為了營救班長不惜鋌而走險(xiǎn)沖鋒陷陣。",
reading: "92",
collection: "65",
headImgSrc: "/images/post/bl.png",
dataTime: "一天前",
author: "妮可",
detail: "伊拉克戰(zhàn)爭時(shí)期,來自美國德州的19歲技術(shù)兵比利·林恩(喬·阿爾文 Joe Alwyn 飾)因?yàn)橐欢闻既慌臄z的視頻而家喻戶曉。那是一次規(guī)模不大卻激烈非常的遭遇戰(zhàn),戰(zhàn)斗中林恩所在的B班班長(范·迪塞爾 Vin Diesel 飾)遭到當(dāng)?shù)匚溲b分子的伏擊和劫持,而林恩為了營救班長不惜鋌而走險(xiǎn)沖鋒陷陣。視頻公布于世讓他成為全美民眾所崇拜的英雄,然而卻鮮有人理解他和戰(zhàn)友們所經(jīng)歷的一切。為了安葬班長,B班得到了短暫的休假,因此他們得以受邀參加一場在德州舉行的橄欖球比賽。林恩的姐姐因某事件深感愧疚,她希望弟弟能借此機(jī)緣回歸普通生活。而周圍的經(jīng)紀(jì)人、球迷、大老板、普通民眾則對戰(zhàn)爭、衛(wèi)國、士兵有著各種各樣想當(dāng)然的理解。球場上的慶典盛大開幕,林恩和戰(zhàn)友們的心卻愈加沉重與焦躁…… ",
postId: 1,
},
{
date: "Jan 05 2018",
title: "肖申克的救贖",
imgSrc: "/images/post/xs.jpg",
avatar: "/images/avatar/3.png",
content: "20世紀(jì)40年代末,小有成就的青年銀行家安迪(蒂姆·羅賓斯 Tim Robbins 飾)因涉嫌殺害妻子及她的情人而鋃鐺入獄。在這座名為肖申克的監(jiān)獄內(nèi),希望似乎虛無縹緲,終身監(jiān)禁的懲罰無疑注定了安迪接下來灰暗絕望的人生。",
reading: "92",
collection: "65",
headImgSrc: "/images/post/xs.jpg",
dataTime: "兩天前",
author: "John",
detail: "20世紀(jì)40年代末,小有成就的青年銀行家安迪(蒂姆·羅賓斯 Tim Robbins 飾)因涉嫌殺害妻子及她的情人而鋃鐺入獄。在這座名為肖申克的監(jiān)獄內(nèi),希望似乎虛無縹緲,終身監(jiān)禁的懲罰無疑注定了安迪接下來灰暗絕望的人生。未過多久,安迪嘗試接近囚犯中頗有聲望的瑞德(摩根·弗里曼 Morgan Freeman 飾),請求對方幫自己搞來小錘子。以此為契機(jī),二人逐漸熟稔,安迪也仿佛在魚龍混雜、罪惡橫生、黑白混淆的牢獄中找到屬于自己的求生之道。他利用自身的專業(yè)知識,幫助監(jiān)獄管理層逃稅、洗黑錢,同時(shí)憑借與瑞德的交往在×××中間也漸漸受到禮遇。表面看來,他已如瑞德那樣對那堵高墻從憎恨轉(zhuǎn)變?yōu)樘幹┤?,但是對自由的渴望仍促使他朝著心中的希望和目?biāo)前進(jìn)。而關(guān)于其罪行的真相,似乎更使這一切朝前推進(jìn)了一步…… ",
postId: 2,
},
{
date: "Jan 01 2018",
title: "霸王別姬",
imgSrc: "/images/post/bj.jpg",
avatar: "/images/avatar/4.png",
content: "段小樓(張豐毅)與程蝶衣(張國榮)是一對打小一起長大的師兄弟,兩人一個(gè)演生,一個(gè)飾旦,一向配合天衣無縫,尤其一出《霸王別姬》,更是譽(yù)滿京城,為此,兩人約定合演一輩子《霸王別姬》。但兩人對戲劇與人生關(guān)系的理解有本質(zhì)不同,段小樓深知戲非人生,程蝶衣則是人戲不分。",
reading: "92",
collection: "65",
headImgSrc: "/images/post/bj.jpg",
dataTime: "三天前",
author: "Jack",
detail: "段小樓(張豐毅)與程蝶衣(張國榮)是一對打小一起長大的師兄弟,兩人一個(gè)演生,一個(gè)飾旦,一向配合天衣無縫,尤其一出《霸王別姬》,更是譽(yù)滿京城,為此,兩人約定合演一輩子《霸王別姬》。但兩人對戲劇與人生關(guān)系的理解有本質(zhì)不同,段小樓深知戲非人生,程蝶衣則是人戲不分。段小樓在認(rèn)為該成家立業(yè)之時(shí)迎娶了名妓菊仙(鞏俐),致使程蝶衣認(rèn)定菊仙是可恥的第三者,使段小樓做了叛徒,自此,三人圍繞一出《霸王別姬》生出的愛恨情仇戰(zhàn)開始隨著時(shí)代風(fēng)云的變遷不斷升級,終釀成悲劇。",
postId: 3,
},
{
date: "Jan 08 2018",
title: "這個(gè)殺手不太冷",
imgSrc: "/images/post/ss.jpg",
avatar: "/images/avatar/5.png",
content: "里昂(讓·雷諾飾)是名孤獨(dú)的×××,受人雇傭。一天,鄰居家小姑娘馬蒂爾達(dá)(納塔麗·波特曼飾)敲開他的房門,要求在他那里暫避殺身之禍。原來鄰居家的主人是警方緝毒組的眼線,只因貪污了一小包×××而遭惡警(加里·奧德曼飾)殺害全家的懲罰。",
reading: "92",
collection: "65",
headImgSrc: "/images/post/ss.jpg",
dataTime: "四天前",
author: "Bill",
detail: "里昂(讓·雷諾飾)是名孤獨(dú)的×××,受人雇傭。一天,鄰居家小姑娘馬蒂爾達(dá)(納塔麗·波特曼飾)敲開他的房門,要求在他那里暫避殺身之禍。原來鄰居家的主人是警方緝毒組的眼線,只因貪污了一小包×××而遭惡警(加里·奧德曼飾)殺害全家的懲罰。馬蒂爾達(dá)得到里昂的留救,幸免于難,并留在里昂那里。里昂教小女孩使槍,她教里昂法文,兩人關(guān)系日趨親密,相處融洽。女孩想著去×××,反倒被抓,里昂及時(shí)趕到,將女孩救回?;祀s著哀怨情仇的正邪之戰(zhàn)漸次升級,更大的沖突在所難免…… ",
postId: 4,
},
{
date: "Jan 04 2018",
title: "阿甘正傳",
imgSrc: "/images/post/ag.jpg",
avatar: "/images/avatar/1.png",
content: "阿甘(湯姆·漢克斯 飾)于二戰(zhàn)結(jié)束后不久出生在美國南方阿拉巴馬州一個(gè)閉塞的小鎮(zhèn),他先天弱智,智商只有75,然而他的媽媽是一個(gè)性格堅(jiān)強(qiáng)的女性,她常常鼓勵(lì)阿甘“傻人有傻?!?,要他自強(qiáng)不息。",
reading: "92",
collection: "65",
headImgSrc: "/images/post/ag.jpg",
dataTime: "五天前",
author: "Tony",
detail: "阿甘(湯姆·漢克斯 飾)于二戰(zhàn)結(jié)束后不久出生在美國南方阿拉巴馬州一個(gè)閉塞的小鎮(zhèn),他先天弱智,智商只有75,然而他的媽媽是一個(gè)性格堅(jiān)強(qiáng)的女性,她常常鼓勵(lì)阿甘“傻人有傻?!保詮?qiáng)不息。阿甘像普通孩子一樣上學(xué),并且認(rèn)識了一生的朋友和至愛珍妮(羅賓·萊特·潘 飾),在珍妮和媽媽的愛護(hù)下,阿甘憑著上帝賜予的“飛毛腿”開始了一生不停的奔跑。阿甘成為橄欖球巨星、越戰(zhàn)英雄、乒乓球外交使者、億萬富翁,但是,他始終忘不了珍妮,幾次匆匆的相聚和離別,更是加深了阿甘的思念。有一天,阿甘收到珍妮的信,他們終于又要見面了……",
postId: 5,
},
]
// 設(shè)置一個(gè)數(shù)據(jù)出口
module.exports = {
// 輸出的是一個(gè)Array對象
postList: local_database,
}
post-detail.js文件內(nèi)容:
var postsData = require('../../../data/posts-data.js')
Page({
onLoad:function(option){
var postId = option.id; // 這里的id對應(yīng)的是url參數(shù)上的id
var postData=postsData.postList[postId];
this.setData({
postData
});
}
})
post-detail.wxml文件內(nèi)容:
<view class='container'>
<image src='{{postData.headImgSrc}}' class='head-iamge'></image>
<image class='audio' src='/images/music/music-start.png'></image>
<view class='author-date'>
<image src='{{postData.avatar}}' class='avatar' ></image>
<text class='author'>{{postData.author}}</text>
<text class='const-text'>發(fā)表于</text>
<text class='date'>{{postData.dataTime}}</text>
</view>
<text class='title'>{{postData.title}}</text>
<view class='tool'>
<view class='circle-img'>
<image src='/images/icon/collection.png'></image>
<image class='share-img' src='/images/icon/share.png'></image>
</view>
<view class='horizon'></view>
</view>
<text class='detail'>{{postData.detail}}</text>
</view>
運(yùn)行效果:
在文章詳情頁中我們需要實(shí)現(xiàn)一個(gè)文章收藏的功能,由于我們沒有使用到服務(wù)器,所以使用本地緩存來記錄這個(gè)文章是否被用戶收藏的一個(gè)狀態(tài)。
小程序中提供了一個(gè)setStorageSync方法來實(shí)現(xiàn)緩存,從方法名也可以看出這個(gè)方法是帶有同步的。除此之外還有一個(gè)異步的緩存方法setStorage,這個(gè)方法可以用于異步緩存數(shù)據(jù)。
注:和緩存相關(guān)的方法,例如得到緩存數(shù)據(jù)、刪除緩存數(shù)據(jù)等方法,都有同步和異步兩個(gè),方法名末尾有Sync的表示同步,否則是異步。
首先演示一下setStorageSync方法的使用方式:
// 第一個(gè)參數(shù)是鍵,第二個(gè)參數(shù)則是需要存儲的數(shù)據(jù)
wx.setStorageSync('key', "Test");
我在post-detail.js文件中的onLoad方法里加入了以上這段代碼,此時(shí)我點(diǎn)擊進(jìn)入文章詳情頁面,就會緩存這個(gè)數(shù)據(jù),緩存數(shù)據(jù)在Storage界面查看:
在小程序中,如果用戶不去主動清除緩存數(shù)據(jù),那么數(shù)據(jù)就會一直存在,所以現(xiàn)在即便我關(guān)閉開發(fā)工具或者重新進(jìn)行編譯,這個(gè)數(shù)據(jù)都會存在,除非我主動刪掉它。
通過鍵可以改變緩存數(shù)據(jù):
wx.setStorageSync('key', {
game:"eat chicken",
developer:"LD",
});
運(yùn)行結(jié)果:
獲取緩存的數(shù)據(jù):
<!-- 在收藏圖標(biāo)上加上一個(gè)事件 -->
<image catchtap='onCollectionTap' src='/images/icon/collection.png'></image>
使用getStorageSync方法即可得到緩存數(shù)據(jù):
onCollectionTap:function(event){
var game=wx.getStorageSync('key');
console.log(game);
}
運(yùn)行結(jié)果:
刪除緩存數(shù)據(jù):
<!-- 在分享圖標(biāo)上加上一個(gè)事件 -->
<image catchtap='onShareTap' class='share-img' src='/images/icon/share.png'></image>
使用removeStorageSync方法即可刪除緩存數(shù)據(jù):
onShareTap:function(event){
wx.removeStorageSync('key');
},
運(yùn)行結(jié)果,可以看到數(shù)據(jù)已經(jīng)不存在了:
刪除所有緩存數(shù)據(jù)的方法:
wx.clearStorageSync();
注:小程序規(guī)定緩存數(shù)據(jù)的大小上限是10MB
實(shí)現(xiàn)這個(gè)功能我們需要使用到兩個(gè)圖標(biāo)進(jìn)行狀態(tài)的輪換,由于小程序中沒有document,我們需要使用if判斷來實(shí)現(xiàn)這個(gè)功能。
post-detail.wxml代碼如下:
<!-- 判斷collected的值是否為真,是的話就顯示src中指定的圖片 -->
<image wx:if="{{collected}}" catchtap='onCollectionTap' src='/images/icon/collection.png'></image>
<!-- 否則顯示這張圖片 -->
<image wx:else catchtap='onCollectionTap' src='/images/icon/collection-anti.png'></image>
post-detail.js代碼如下:
var postsData = require('../../../data/posts-data.js')
Page({
data:{
},
onLoad: function (option) {
var postId = option.id; // 這里的id對應(yīng)的是url參數(shù)上的id
// 把postId設(shè)置到數(shù)據(jù)集里,這樣就能夠全局獲取
this.data.currentPostId = postId;
var postData = postsData.postList[postId];
this.setData({
postData
});
// 從緩存中獲取數(shù)據(jù),鍵值對形式的
var postsCollected = wx.getStorageSync('posts_collected');
// 判斷數(shù)據(jù)是否不為空
if (postsCollected) {
// 不為空就拿出與postId對應(yīng)的下標(biāo)值
var postsCollected = postsCollected[postId];
// 并將值更新到數(shù)據(jù)綁定里
this.setData({
collected: postsCollected
});
} else {
// 如果為空就賦值一個(gè)空對象
var postsCollected = {}
// 并把與postId對應(yīng)的下標(biāo)中的值設(shè)置為false
postsCollected[postId] = false;
// 更新到緩存里
wx.setStorageSync('posts_collected', postsCollected);
}
},
// 點(diǎn)擊事件方法
onCollectionTap: function (event) {
// 獲取緩存數(shù)據(jù)
var postsCollected = wx.getStorageSync('posts_collected');
// 從數(shù)據(jù)集中獲取postId
var postCollected = postsCollected[this.data.currentPostId];
// 收藏變成未收藏,未收藏變成收藏
postCollected = !postCollected;
postsCollected[this.data.currentPostId] = postCollected;
// 更新文章是否收藏的緩存值
wx.setStorageSync('posts_collected', postsCollected);
// 更新數(shù)據(jù)綁定變量,從而實(shí)現(xiàn)切換圖片
this.setData({
collected: postCollected
});
},
})
運(yùn)行效果:
未收藏狀態(tài):
收藏狀態(tài):
以上我們實(shí)現(xiàn)了收藏和未收藏圖標(biāo)的一個(gè)輪換功能,但是還缺少了個(gè)提示功能,在用戶點(diǎn)擊收藏時(shí)要提示用戶收藏成功,再次點(diǎn)擊則需要提示用戶取消成功。
小程序提供了幾個(gè)實(shí)現(xiàn)交互反饋功能的API,詳情參考以下官方文檔:
https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-react.html
我們需要使用到其中三個(gè)API,分別是wx.showToast、wx.showModal、wx.showActionSheet。
首先來應(yīng)用wx.showToast這個(gè)API,在事件方法中,加入如下代碼:
wx.showToast({
// 使用三元表達(dá)式來判斷狀態(tài)
title: postCollected ? '收藏成功!' :'取消成功!',
// 設(shè)置圖標(biāo)停留的時(shí)間,單位是毫秒
duration: 1000,
// icon可以設(shè)置圖標(biāo),默認(rèn)就是success
icon: "success",
});
運(yùn)行效果:
wx.showModal可以顯示模態(tài)彈窗,我們可以把wx.showModal與wx.showToast相結(jié)合使用。
修改代碼如下:
var postsData = require('../../../data/posts-data.js')
Page({
data: {
},
onLoad: function (option) {
var postId = option.id; // 這里的id對應(yīng)的是url參數(shù)上的id
// 把postId設(shè)置到數(shù)據(jù)集里,這樣就能夠全局獲取
this.data.currentPostId = postId;
var postData = postsData.postList[postId];
this.setData({
postData
});
// 從緩存中獲取數(shù)據(jù)
var postsCollected = wx.getStorageSync('posts_collected');
// 判斷數(shù)據(jù)是否不為空
if (postsCollected) {
// 不為空就拿出與postId對應(yīng)的下標(biāo)值
var postsCollected = postsCollected[postId];
// 并將值更新到數(shù)據(jù)綁定里
this.setData({
collected: postsCollected
});
} else {
// 如果為空就賦值一個(gè)空對象
var postsCollected = {}
// 并把與postId對應(yīng)的下標(biāo)中的值設(shè)置為false
postsCollected[postId] = false;
// 更新到緩存里
wx.setStorageSync('posts_collected', postsCollected);
}
},
// 點(diǎn)擊事件方法
onCollectionTap: function (event) {
// 獲取緩存數(shù)據(jù)
var postsCollected = wx.getStorageSync('posts_collected');
// 獲取postId
var postCollected = postsCollected[this.data.currentPostId];
// 收藏變成未收藏,未收藏變成收藏
postCollected = !postCollected;
postsCollected[this.data.currentPostId] = postCollected;
// 自定義函數(shù)也需要使用this來訪問
this.showModal(postsCollected, postCollected);
},
showModal: function (postsCollected, postCollected){
// 把this指代的Page對象先存儲起來
var that = this;
wx.showModal({
title: '收藏',
content: postCollected ? '是否收藏該文章?' :'是否取消收藏該文章?',
showCancel: 'true',
cancelText: '取消',
cancelColor: '#333',
confirmText: '確認(rèn)',
confirmColor: '#405f80',
success:function(res){
if(res.confirm){
// 更新文章是否收藏的緩存值
wx.setStorageSync('posts_collected', postsCollected);
// 更新數(shù)據(jù)綁定變量,從而實(shí)現(xiàn)切換圖片
that.setData({
collected: postCollected
});
that.showToast(postsCollected, postCollected);
}
},
});
},
showToast: function (postsCollected, postCollected){
wx.showToast({
// 使用三元表達(dá)式來判斷狀態(tài)
title: postCollected ? '收藏成功!' : '取消成功!',
// 設(shè)置圖標(biāo)停留的時(shí)間,單位是毫秒
duration: 1000,
// icon可以設(shè)置圖標(biāo),默認(rèn)就是success
icon: "success",
});
},
})
運(yùn)行效果:
收藏:
取消收藏:
注:在實(shí)際開發(fā)中這種成本低的操作是不需要把交互反饋?zhàn)龅眠@么麻煩的,一般只使用showToast即可。所謂成本指的是誤操作帶來的損失,如果成本低的操作交互反饋太麻煩的話,會感覺體驗(yàn)不好。
?showActionSheet可以顯示操作菜單,以下使用實(shí)際示例演示一下showActionSheet的使用:
1.在分享圖標(biāo)上加上一個(gè)點(diǎn)擊事件:
<image catchtap='onShareTap' class='share-img' src='/images/icon/share.png'></image>
2.事件代碼如下:
onShareTap:function(event){
var itemList = [
"分享給微信好友",
"分享到朋友圈",
"分享到QQ",
"分享到微博",
]
wx.showActionSheet({
itemList: itemList, // 按鈕的文字?jǐn)?shù)組,數(shù)組長度最大為6個(gè)
itemColor:"#405f80", // 設(shè)置字體顏色
success:function(res){
//res.tapIndex 用戶點(diǎn)擊的按鈕,從上到下的順序,從0開始
wx.showModal({
title: itemList[res.tapIndex],
content: '現(xiàn)在無法實(shí)現(xiàn)分享功能,什么時(shí)候能支持還未知',
})
},
})
},
運(yùn)行效果:
注:到目前為止,微信小程序官方還尚未提供能夠?qū)⑿〕绦蛑苯臃窒淼脚笥讶Φ南嚓P(guān)api,不過有一些曲線救國的方案,可以參考以下兩篇文章,或者使用百度、谷歌等搜索引擎搜索解決方案:
https://segmentfault.com/a/1190000012316892
http://blog.csdn.net/baozhuona/article/details/78570483
我們把之前的onCollectionTap方法中的同步獲取緩存的方法改為異步獲取緩存的方法,以此來演示同步與異步方法之間的區(qū)別,修改代碼如下:
onCollectionTap: function (event) {
// 把當(dāng)前this指代的當(dāng)前對象先存儲起來
var that = this;
// 異步獲取緩存數(shù)據(jù)
var postsCollected = wx.getStorage({
key: 'posts_collected',
success: function (res) {
var postsCollected = res.data;
// 獲取postId
var postCollected = postsCollected[that.data.currentPostId];
// 收藏變成未收藏,未收藏變成收藏
postCollected = !postCollected;
postsCollected[that.data.currentPostId] = postCollected;
that.showModal(postsCollected, postCollected);
},
});
},
以上就是異步方法的實(shí)現(xiàn)方式,與同步方法的主要區(qū)別在于,同步會等待wx.getStorageSync('posts_collected');方法執(zhí)行完之后才會往下執(zhí)行,所以如果當(dāng)獲取緩存得很慢的時(shí)候,操作界面就會卡在那。而異步則不會,異步獲取緩存數(shù)據(jù)的時(shí)候,代碼還會繼續(xù)往下執(zhí)行,異步獲取完成之后再執(zhí)行success里的方法。
注:通常情況下,在小程序中必須要使用異步方法的情況比較少,建議如果對異步方法不熟悉的話,最好不要使用異步方法,不然不僅會讓你的代碼變得難以閱讀,而且很容易埋下一些隱藏bug,或者難以解決的錯(cuò)誤。至于使用異步還是同步,需要根據(jù)業(yè)務(wù)來決定,當(dāng)可以使用同步的情況下,優(yōu)先使用同步。
以上我們已經(jīng)完成了文章詳情頁的大部分內(nèi)容,現(xiàn)在還剩一個(gè)音樂播放功能還未實(shí)現(xiàn),官方也提供了一個(gè)audio組件可以實(shí)現(xiàn)音樂播放。除了組件之外還有相關(guān)的API可以使用,在這里我們使用API來實(shí)現(xiàn)音樂播放功能,因?yàn)槭褂肁PI的方式比較方便于自定義。
官方文檔:
API:https://mp.weixin.qq.com/debug/wxadoc/dev/api/media-voice.html
組件:https://mp.weixin.qq.com/debug/wxadoc/dev/component/audio.html
我們需要使用到兩個(gè)API,playBackgroundAudio以及pauseBackgroundAudio。前者是用于音樂的播放,后者是用于音樂的暫停。
先給音樂圖標(biāo)添加一個(gè)事件,并且使用三元運(yùn)算符來判斷圖標(biāo)是顯示暫停圖標(biāo)還是啟動圖標(biāo):
<image catchtap='onMusicTap' class='audio' src='{{isPlayingMusic ? "/images/music/music-stop.png" : "/images/music/music-start.png"}}'></image>
事件方法實(shí)現(xiàn)代碼如下:
data: {
isPlayingMusic: false
},
onMusicTap: function (event) {
// 獲取數(shù)據(jù)文件中的數(shù)據(jù)
var currentPostId = this.data.currentPostId;
var postData = postsData.postList[currentPostId];
// 使用變量來記錄音樂的狀態(tài)
var isPlayingMusic = this.data.isPlayingMusic;
if (isPlayingMusic) {
// 暫停音樂
wx.pauseBackgroundAudio();
// 改變狀態(tài)
this.setData({
isPlayingMusic : false
});
} else {
wx.playBackgroundAudio({
// 流媒體文件的URL,目前支持的格式有 m4a, aac, mp3, wav
dataUrl: postData.music.url,
// 音樂標(biāo)題
title: postData.music.title,
// 音樂封面URL
coverImgUrl: postData.music.coverImg,
})
// 改變狀態(tài)
this.setData({
isPlayingMusic: true
});
}
},
注:dataUrl只能夠是引用流媒體文件,不能夠使用本地的音樂文件,coverImgUrl也是如此,因?yàn)樾〕绦虻拇笮∠拗剖?M,一個(gè)音樂文件都不止1M了,所以只能使用流媒體文件的URL形式引入音樂。coverImgUrl引入的圖片只有在真機(jī)上才能看到得到。
數(shù)據(jù)文件內(nèi)容如下,增加了音樂連接、音樂標(biāo)題、音樂圖片屬性:
// 將數(shù)據(jù)整合成數(shù)組類型
var local_database = [
{
date: "Jan 06 2018",
title: "正是蝦肥蟹壯時(shí)",
imgSrc: "/images/post/crab.png",
avatar: "/images/avatar/1.png",
content: "“山明水凈夜來霜,數(shù)樹深紅出淺黃。試上高樓清入骨,豈如春色嗾人狂。”金秋時(shí)節(jié),天高云淡,秋風(fēng)送爽,氣候宜人。秋風(fēng)秋陽中,碩果墜掛枝頭,玉米撫須含笑,高粱引頸高歌,豆莢飽滿圓潤。",
reading: "112",
collection: "96",
headImgSrc: "/images/post/crab.png",
author: "zero",
dataTime:"24小時(shí)前",
detail: "“山明水凈夜來霜,數(shù)樹深紅出淺黃。試上高樓清入骨,豈如春色嗾人狂?!苯鹎飼r(shí)節(jié),天高云淡,秋風(fēng)送爽,氣候宜人。秋風(fēng)秋陽中,碩果墜掛枝頭,玉米撫須含笑,高粱引頸高歌,豆莢飽滿圓潤。棉桃鼓脹欲裂,水稻灌漿初熟,世間萬物經(jīng)過春的孕育,夏的生長,即將抵達(dá)收獲的季節(jié)。在這瓜果飄香、稻黍起舞的召喚聲中,又是一度蟹肥蝦壯時(shí)。地處黃海之濱的小城,在秋風(fēng)的撫慰、秋陽的光照下,瞬間也喧囂起來。任意走進(jìn)城中的每一個(gè)菜市場,在顯眼的位置上,沖入耳際的是此起彼伏的吆喝聲,映入眼簾的是那些小商小販們搶占有利地勢將一只只塑料箱一字排開的情景。淺箱中,健壯的對蝦、竹節(jié)蝦在水中跳躍,舒展著彎曲的身體;深箱中,一貫橫行霸道的螃蟹擁擠在狹小的空間里,相互肆意踐踏,有些不甘蝸居的螃蟹,順著筆直的箱壁艱難地攀爬著,雖經(jīng)百般努力,終以失敗而告終。那些聚集在網(wǎng)兜里的螃蟹,更是不甘寂寞,身體被束縛著無法動彈,便利用可以自由呼吸的嘴巴,于窸窸窣窣中不停地吐著一串串泡沫,以示抗議,也以此證明自己是個(gè)活物。特別是那些個(gè)頭較大的螃蟹,仿佛知道自己的身價(jià)不菲,為此,更是氣宇軒昂,自以為是。也許,它們是得到垂青和恩寵的一類吧,受到了特別的眷顧,活動的空間相對較大,所以也更加肆無忌憚。只要有人試圖靠近,便會舉著那兩只肥碩的大螯向你示威,仿佛在警告你:別碰我,否則休怪我無禮!",
postId: 0,
music: {
url: "http://ws.stream.qqmusic.qq.com/C100003507bR0gDKBm.m4a?fromtag=38",
title: "夜夜夜夜-齊秦",
coverImg: "http://y.gtimg.cn/music/photo_new/T002R150x150M000001TEc6V0kjpVC.jpg?max_age=2592000"
}
},
{
date: "Jan 03 2018",
title: "比利·林恩的中場戰(zhàn)事",
imgSrc: "/images/post/bl.png",
avatar: "/images/avatar/2.png",
content: "伊拉克戰(zhàn)爭時(shí)期,來自美國德州的19歲技術(shù)兵比利·林恩(喬·阿爾文 Joe Alwyn 飾)因?yàn)橐欢闻既慌臄z的視頻而家喻戶曉。那是一次規(guī)模不大卻激烈非常的遭遇戰(zhàn),戰(zhàn)斗中林恩所在的B班班長(范·迪塞爾 Vin Diesel 飾)遭到當(dāng)?shù)匚溲b分子的伏擊和劫持,而林恩為了營救班長不惜鋌而走險(xiǎn)沖鋒陷陣。",
reading: "92",
collection: "65",
headImgSrc: "/images/post/bl.png",
dataTime: "一天前",
author: "妮可",
detail: "伊拉克戰(zhàn)爭時(shí)期,來自美國德州的19歲技術(shù)兵比利·林恩(喬·阿爾文 Joe Alwyn 飾)因?yàn)橐欢闻既慌臄z的視頻而家喻戶曉。那是一次規(guī)模不大卻激烈非常的遭遇戰(zhàn),戰(zhàn)斗中林恩所在的B班班長(范·迪塞爾 Vin Diesel 飾)遭到當(dāng)?shù)匚溲b分子的伏擊和劫持,而林恩為了營救班長不惜鋌而走險(xiǎn)沖鋒陷陣。視頻公布于世讓他成為全美民眾所崇拜的英雄,然而卻鮮有人理解他和戰(zhàn)友們所經(jīng)歷的一切。為了安葬班長,B班得到了短暫的休假,因此他們得以受邀參加一場在德州舉行的橄欖球比賽。林恩的姐姐因某事件深感愧疚,她希望弟弟能借此機(jī)緣回歸普通生活。而周圍的經(jīng)紀(jì)人、球迷、大老板、普通民眾則對戰(zhàn)爭、衛(wèi)國、士兵有著各種各樣想當(dāng)然的理解。球場上的慶典盛大開幕,林恩和戰(zhàn)友們的心卻愈加沉重與焦躁…… ",
postId: 1,
music: {
url: "http://ws.stream.qqmusic.qq.com/C100003GdCmG4NkEOR.m4a?fromtag=38",
title: "鬼迷心竅-李宗盛",
coverImg: "http://y.gtimg.cn/music/photo_new/T002R150x150M000002xOmp62kqSic.jpg?max_age=2592000"
}
},
{
date: "Jan 05 2018",
title: "肖申克的救贖",
imgSrc: "/images/post/xs.jpg",
avatar: "/images/avatar/3.png",
content: "20世紀(jì)40年代末,小有成就的青年銀行家安迪(蒂姆·羅賓斯 Tim Robbins 飾)因涉嫌殺害妻子及她的情人而鋃鐺入獄。在這座名為肖申克的監(jiān)獄內(nèi),希望似乎虛無縹緲,終身監(jiān)禁的懲罰無疑注定了安迪接下來灰暗絕望的人生。",
reading: "92",
collection: "65",
headImgSrc: "/images/post/xs.jpg",
dataTime: "兩天前",
author: "John",
detail: "20世紀(jì)40年代末,小有成就的青年銀行家安迪(蒂姆·羅賓斯 Tim Robbins 飾)因涉嫌殺害妻子及她的情人而鋃鐺入獄。在這座名為肖申克的監(jiān)獄內(nèi),希望似乎虛無縹緲,終身監(jiān)禁的懲罰無疑注定了安迪接下來灰暗絕望的人生。未過多久,安迪嘗試接近囚犯中頗有聲望的瑞德(摩根·弗里曼 Morgan Freeman 飾),請求對方幫自己搞來小錘子。以此為契機(jī),二人逐漸熟稔,安迪也仿佛在魚龍混雜、罪惡橫生、黑白混淆的牢獄中找到屬于自己的求生之道。他利用自身的專業(yè)知識,幫助監(jiān)獄管理層逃稅、洗黑錢,同時(shí)憑借與瑞德的交往在×××中間也漸漸受到禮遇。表面看來,他已如瑞德那樣對那堵高墻從憎恨轉(zhuǎn)變?yōu)樘幹┤?,但是對自由的渴望仍促使他朝著心中的希望和目?biāo)前進(jìn)。而關(guān)于其罪行的真相,似乎更使這一切朝前推進(jìn)了一步…… ",
postId: 2,
music: {
url: "http://ws.stream.qqmusic.qq.com/C100004HLusI2lLjZy.m4a?fromtag=38",
title: "女兒情-萬曉利",
coverImg: "http://y.gtimg.cn/music/photo_new/T002R150x150M000004Wv5BO30pPc0.jpg?max_age=2592000"
}
},
{
date: "Jan 01 2018",
title: "霸王別姬",
imgSrc: "/images/post/bj.jpg",
avatar: "/images/avatar/4.png",
content: "段小樓(張豐毅)與程蝶衣(張國榮)是一對打小一起長大的師兄弟,兩人一個(gè)演生,一個(gè)飾旦,一向配合天衣無縫,尤其一出《霸王別姬》,更是譽(yù)滿京城,為此,兩人約定合演一輩子《霸王別姬》。但兩人對戲劇與人生關(guān)系的理解有本質(zhì)不同,段小樓深知戲非人生,程蝶衣則是人戲不分。",
reading: "92",
collection: "65",
headImgSrc: "/images/post/bj.jpg",
dataTime: "三天前",
author: "Jack",
detail: "段小樓(張豐毅)與程蝶衣(張國榮)是一對打小一起長大的師兄弟,兩人一個(gè)演生,一個(gè)飾旦,一向配合天衣無縫,尤其一出《霸王別姬》,更是譽(yù)滿京城,為此,兩人約定合演一輩子《霸王別姬》。但兩人對戲劇與人生關(guān)系的理解有本質(zhì)不同,段小樓深知戲非人生,程蝶衣則是人戲不分。段小樓在認(rèn)為該成家立業(yè)之時(shí)迎娶了名妓菊仙(鞏俐),致使程蝶衣認(rèn)定菊仙是可恥的第三者,使段小樓做了叛徒,自此,三人圍繞一出《霸王別姬》生出的愛恨情仇戰(zhàn)開始隨著時(shí)代風(fēng)云的變遷不斷升級,終釀成悲劇。",
postId: 3,
music: {
url: "http://ws.stream.qqmusic.qq.com/C100002mWVx72p8Ugp.m4a?fromtag=38",
title: "戀戀風(fēng)塵-老狼",
coverImg: "http://y.gtimg.cn/music/photo_new/T002R150x150M000001VaXQX1Z1Imq.jpg?max_age=2592000",
}
},
{
date: "Jan 08 2018",
title: "這個(gè)殺手不太冷",
imgSrc: "/images/post/ss.jpg",
avatar: "/images/avatar/5.png",
content: "里昂(讓·雷諾飾)是名孤獨(dú)的×××,受人雇傭。一天,鄰居家小姑娘馬蒂爾達(dá)(納塔麗·波特曼飾)敲開他的房門,要求在他那里暫避殺身之禍。原來鄰居家的主人是警方緝毒組的眼線,只因貪污了一小包×××而遭惡警(加里·奧德曼飾)殺害全家的懲罰。",
reading: "92",
collection: "65",
headImgSrc: "/images/post/ss.jpg",
dataTime: "四天前",
author: "Bill",
detail: "里昂(讓·雷諾飾)是名孤獨(dú)的×××,受人雇傭。一天,鄰居家小姑娘馬蒂爾達(dá)(納塔麗·波特曼飾)敲開他的房門,要求在他那里暫避殺身之禍。原來鄰居家的主人是警方緝毒組的眼線,只因貪污了一小包×××而遭惡警(加里·奧德曼飾)殺害全家的懲罰。馬蒂爾達(dá)得到里昂的留救,幸免于難,并留在里昂那里。里昂教小女孩使槍,她教里昂法文,兩人關(guān)系日趨親密,相處融洽。女孩想著去×××,反倒被抓,里昂及時(shí)趕到,將女孩救回?;祀s著哀怨情仇的正邪之戰(zhàn)漸次升級,更大的沖突在所難免…… ",
postId: 4,
music: {
url: "http://ws.stream.qqmusic.qq.com/C100000Zn0vS4fKKo8.m4a?fromtag=38",
title: "沉默是金-張國榮",
coverImg: "http://y.gtimg.cn/music/photo_new/T002R150x150M000003at0mJ2YrR2H.jpg?max_age=2592000"
}
},
{
date: "Jan 04 2018",
title: "阿甘正傳",
imgSrc: "/images/post/ag.jpg",
avatar: "/images/avatar/1.png",
content: "阿甘(湯姆·漢克斯 飾)于二戰(zhàn)結(jié)束后不久出生在美國南方阿拉巴馬州一個(gè)閉塞的小鎮(zhèn),他先天弱智,智商只有75,然而他的媽媽是一個(gè)性格堅(jiān)強(qiáng)的女性,她常常鼓勵(lì)阿甘“傻人有傻福”,要他自強(qiáng)不息。",
reading: "92",
collection: "65",
headImgSrc: "/images/post/ag.jpg",
dataTime: "五天前",
author: "Tony",
detail: "阿甘(湯姆·漢克斯 飾)于二戰(zhàn)結(jié)束后不久出生在美國南方阿拉巴馬州一個(gè)閉塞的小鎮(zhèn),他先天弱智,智商只有75,然而他的媽媽是一個(gè)性格堅(jiān)強(qiáng)的女性,她常常鼓勵(lì)阿甘“傻人有傻福”,要他自強(qiáng)不息。阿甘像普通孩子一樣上學(xué),并且認(rèn)識了一生的朋友和至愛珍妮(羅賓·萊特·潘 飾),在珍妮和媽媽的愛護(hù)下,阿甘憑著上帝賜予的“飛毛腿”開始了一生不停的奔跑。阿甘成為橄欖球巨星、越戰(zhàn)英雄、乒乓球外交使者、億萬富翁,但是,他始終忘不了珍妮,幾次匆匆的相聚和離別,更是加深了阿甘的思念。有一天,阿甘收到珍妮的信,他們終于又要見面了……",
postId: 5,
music: {
url: "http://ws.stream.qqmusic.qq.com/C100002I8eGJ28BI17.m4a?fromtag=38",
title: "朋友-譚詠麟",
coverImg: "http://y.gtimg.cn/music/photo_new/T002R150x150M000004eGsCN3SUheO.jpg?max_age=2592000"
}
},
]
// 設(shè)置一個(gè)數(shù)據(jù)出口
module.exports = {
// 輸出的是一個(gè)Array對象
postList: local_database,
}
運(yùn)行效果:
播放:
暫停:
以上我們完成了簡單的音樂播放和暫停以及音樂圖標(biāo)的切換,而且也說明了coverImg中引入的圖片只有在真機(jī)上,進(jìn)入音樂界面后才能夠看到,但是我們也可以將coverImg引入的圖片顯示在文章詳情頁上,只需要做一個(gè)簡單的圖片切換即可:
<image src='{{isPlayingMusic ? postData.music.coverImg : postData.headImgSrc}}' class='head-iamge'></image>
運(yùn)行效果:
播放:
暫停:
在音樂播放的時(shí)候,可以看到會彈出來一個(gè)音樂播放的總控開關(guān),我們點(diǎn)擊音樂圖標(biāo)的時(shí)候能夠正常的切換圖片,但是點(diǎn)擊總控開關(guān)的時(shí)候不會切換圖片,這是因?yàn)槲覀冎槐O(jiān)聽了圖標(biāo)上的事件,沒有監(jiān)聽音樂播放、暫停的事件。所以我們還需要完善這點(diǎn)小細(xì)節(jié),讓點(diǎn)擊總控開關(guān)的時(shí)候也能切換圖片,實(shí)現(xiàn)這一步需要使用到兩個(gè)API,onBackgroundAudioPlay以及onBackgroundAudioPause,前者用于監(jiān)聽音樂播放,后者用于監(jiān)聽音樂暫停。
在onLoad生命周期方法中增加以下代碼:
var that = this;
// 當(dāng)音樂播放時(shí)將isPlayingMusic狀態(tài)改為true
wx.onBackgroundAudioPlay(function(){
that.setData({
isPlayingMusic: true
});
});
// 當(dāng)音樂暫停時(shí)將isPlayingMusic狀態(tài)改為false
wx.onBackgroundAudioPause(function(){
that.setData({
isPlayingMusic: false
});
})
加入以上代碼后就可以實(shí)現(xiàn)點(diǎn)擊總控開關(guān)也能切換圖片,而且以上代碼也體現(xiàn)出了數(shù)據(jù)綁定機(jī)制的好處,只需要修改數(shù)據(jù)集中相應(yīng)數(shù)據(jù)的值即可,無需每次都去獲得節(jié)點(diǎn)對象后才能操作相應(yīng)的數(shù)據(jù)的值。
文章詳情頁中的音樂播放功能看起來基本是沒什么問題了,不過這也僅限于文章詳情這一個(gè)頁面內(nèi)而已,如果我點(diǎn)擊了播放音樂,然后返回到上一級頁面,再點(diǎn)擊進(jìn)入文章詳情頁的話,頁面的狀態(tài)就會是初始化時(shí)的狀態(tài),這時(shí)音樂圖片就不會自動切換到播放狀態(tài)的圖片。這是因?yàn)槲覀兊臓顟B(tài)代碼寫在js文件的Page對象里,會受到頁面生命周期的影響,當(dāng)我們返回上一級頁面,再點(diǎn)擊進(jìn)入文章詳情頁時(shí),Page對象會被加載,頁面代碼就會被重新執(zhí)行一遍,所以音樂圖標(biāo)的狀態(tài)就會是初始時(shí)的狀態(tài)。
解決這個(gè)問題我們需要用到全局變量來保存狀態(tài),全局變量不會受頁面生命周期的影響,而且在任何頁面中都可以獲取到全局變量的值。在小程序中全局變量需要寫在app.js文件中,該文件中的代碼需要寫在App對象里,就像我們的頁面代碼需要寫在Page中一樣,Page代表的是一個(gè)頁面,而App對象則是代表著整個(gè)應(yīng)用程序,該對象的生命周期也就是應(yīng)用程序的生命周期。以下是該對象的生命周期方法:
App({
/**
* 當(dāng)小程序初始化完成時(shí),會觸發(fā) onLaunch(全局只觸發(fā)一次)
*/
onLaunch: function () {
},
/**
* 當(dāng)小程序啟動,或從后臺進(jìn)入前臺顯示,會觸發(fā) onShow
*/
onShow: function (options) {
},
/**
* 當(dāng)小程序從前臺進(jìn)入后臺,會觸發(fā) onHide
*/
onHide: function () {
},
/**
* 當(dāng)小程序發(fā)生腳本錯(cuò)誤,或者 api 調(diào)用失敗時(shí),會觸發(fā) onError 并帶上錯(cuò)誤信息
*/
onError: function (msg) {
}
})
以上我們簡單介紹了一下關(guān)于頁面狀態(tài)與全局變量以及應(yīng)用程序生命周期,現(xiàn)在就可以使用全局變量來繼續(xù)完善音樂播放的功能了:
app.js代碼如下:
App({
globalData:{
g_isPlayingMusic:false
},
});
post-detail.js代碼如下:
var postsData = require('../../../data/posts-data.js')
// 獲得全局的app對象
var app = getApp();
Page({
data: {
isPlayingMusic: false
},
onLoad: function (option) {
......以上代碼省略......
// 當(dāng)全局變量的狀態(tài)為播放時(shí),也把頁面的狀態(tài)設(shè)置為teur
if (app.globalData.g_isPlayingMusic){
this.setData({
isPlayingMusic: true
});
}
this.setMusicMonitor();
},
// 把監(jiān)聽音樂的事件代碼提取出來
setMusicMonitor:function(){
var that = this;
// 當(dāng)音樂播放時(shí)將頁面以及全局狀態(tài)狀態(tài)改為true
wx.onBackgroundAudioPlay(function () {
that.setData({
isPlayingMusic: true
});
app.globalData.g_isPlayingMusic = true;
});
// 當(dāng)音樂暫停時(shí)將頁面以及全局狀態(tài)都改為false
wx.onBackgroundAudioPause(function () {
that.setData({
isPlayingMusic: false
});
app.globalData.g_isPlayingMusic = false;
});
},
......以下代碼省略......
})
使用全局變量記錄狀態(tài)后,就不會出現(xiàn)之前的問題了,這時(shí)我們就可以在頁面加載時(shí)根據(jù)全局變量來設(shè)置頁面變量的狀態(tài)。
除了以上的問題之外,我還找到了三個(gè)問題,第一個(gè)問題是當(dāng)我們點(diǎn)擊音樂播放時(shí),背景圖片會切換,但是我們只需要切換當(dāng)前頁面的圖片,別的頁面不應(yīng)該也跟著切換,而這個(gè)問題就是別的頁面也會跟著切換圖片,這個(gè)問題我們可以通過把頁面id存儲到全局變量里,根據(jù)id來決定是哪個(gè)頁面才會切換圖片,這樣就可以解決這個(gè)問題。
第二個(gè)問題是當(dāng)我們關(guān)閉音樂播放器時(shí),圖片不會切換,依舊停留在播放狀態(tài),這個(gè)問題我們可以通過wx.onBackgroundAudioStop來解決。
第三個(gè)問題就是當(dāng)我們在文章A里播放了音樂,然后到文章B上點(diǎn)擊音樂播放器的總控開關(guān)時(shí),文章B的圖片也會跟著切換,解決這個(gè)問題稍微有點(diǎn)麻煩,因?yàn)橐紤]到點(diǎn)擊圖標(biāo)開關(guān)和點(diǎn)擊音樂播放器開關(guān)兩種情況,以及回到原本的頁面時(shí)還需切換圖片,我的解決思路是使用一個(gè)全局變量記錄上一個(gè)頁面,也就是原始頁面的id,通過這個(gè)id來決定切不切換圖片。
app.js文件內(nèi)容如下:
App({
globalData:{
g_isPlayingMusic:false,
g_currentMusicPostId:"",
g_beforeMusicPostId: ""
},
});
以下是修改后的post-detail.js文件內(nèi)容:
var postsData = require('../../../data/posts-data.js')
// 獲得全局的app對象
var app = getApp();
Page({
data: {
isPlayingMusic: false
},
onLoad: function (option) {
var postId = option.id; // 這里的id對應(yīng)的是url參數(shù)上的id
// 把postId設(shè)置到數(shù)據(jù)集里,這樣就能夠全局獲取
this.data.currentPostId = postId;
var postData = postsData.postList[postId];
this.setData({
postData
});
// 從緩存中獲取數(shù)據(jù)
var postsCollected = wx.getStorageSync('posts_collected');
// 判斷數(shù)據(jù)是否不為空
if (postsCollected) {
// 不為空就拿出與postId對應(yīng)的下標(biāo)值
var postsCollected = postsCollected[postId];
// 并將值更新到數(shù)據(jù)綁定里
this.setData({
collected: postsCollected
});
} else {
// 如果為空就賦值一個(gè)空對象
var postsCollected = {}
// 并把與postId對應(yīng)的下標(biāo)中的值設(shè)置為false
postsCollected[postId] = false;
// 更新到緩存里
wx.setStorageSync('posts_collected', postsCollected);
}
// 音樂在播放時(shí)改變狀態(tài)為true
if (app.globalData.g_isPlayingMusic && app.globalData.g_currentMusicPostId === postId){
this.setData({
isPlayingMusic: true
});
}
this.setMusicMonitor();
},
// 把監(jiān)聽音樂的事件代碼提取出來
setMusicMonitor:function(){
var that = this;
// 監(jiān)聽音樂播放
wx.onBackgroundAudioPlay(function () {
// 在原始頁面觸發(fā)播放事件時(shí),切換頁面圖片,并且記錄當(dāng)前文章的id
if (app.globalData.g_beforeMusicPostId != "" && app.globalData.g_beforeMusicPostId === that.data.currentPostId){
that.setData({
isPlayingMusic: true
});
app.globalData.g_isPlayingMusic = true;
app.globalData.g_currentMusicPostId = that.data.currentPostId;
app.globalData.g_beforeMusicPostId = app.globalData.g_beforeMusicPostId;
// 產(chǎn)生原始頁面時(shí),或者圖標(biāo)開關(guān)被點(diǎn)擊時(shí),切換頁面圖片,并且記錄當(dāng)前文章的id
} else if (app.globalData.g_beforeMusicPostId == "" || that.data.isPlayingMusic){
that.setData({
isPlayingMusic: true
});
app.globalData.g_isPlayingMusic = true;
app.globalData.g_currentMusicPostId = that.data.currentPostId;
app.globalData.g_beforeMusicPostId = that.data.currentPostId;
// 在非原始頁面觸發(fā)播放事件時(shí),不切換該頁面的圖片
} else{
that.setData({
isPlayingMusic: false
});
app.globalData.g_isPlayingMusic = true;
app.globalData.g_currentMusicPostId = app.globalData.g_beforeMusicPostId;
}
});
// 當(dāng)音樂暫停時(shí)將頁面以及全局狀態(tài)都改為false,并且把當(dāng)前文章的id清空
wx.onBackgroundAudioPause(function () {
that.setData({
isPlayingMusic: false
});
app.globalData.g_isPlayingMusic = false;
app.globalData.g_currentMusicPostId = "";
});
// 當(dāng)音樂停止時(shí)將頁面以及全局狀態(tài)都改為false,并且把當(dāng)前文章以及上一篇文章的id清空
wx.onBackgroundAudioStop(function(){
that.setData({
isPlayingMusic: false
});
app.globalData.g_isPlayingMusic = false;
app.globalData.g_currentMusicPostId = "";
app.globalData.g_beforeMusicPostId = "";
});
},
//點(diǎn)擊事件方法
onCollectionTap: function (event) {
// 獲取緩存數(shù)據(jù)
var postsCollected = wx.getStorageSync('posts_collected');
// 獲取postId
var postCollected = postsCollected[this.data.currentPostId];
// 收藏變成未收藏,未收藏變成收藏
postCollected = !postCollected;
postsCollected[this.data.currentPostId] = postCollected;
// 自定義函數(shù)也需要使用this來訪問
this.showModal(postsCollected, postCollected);
},
showModal: function (postsCollected, postCollected) {
// 把this指代的Page對象先存儲起來
var that = this;
wx.showModal({
title: '收藏',
content: postCollected ? '是否收藏該文章?' : '是否取消收藏該文章?',
showCancel: 'true',
cancelText: '取消',
cancelColor: '#333',
confirmText: '確認(rèn)',
confirmColor: '#405f80',
success: function (res) {
if (res.confirm) {
// 更新文章是否收藏的緩存值
wx.setStorageSync('posts_collected', postsCollected);
// 更新數(shù)據(jù)綁定變量,從而實(shí)現(xiàn)切換圖片
that.setData({
collected: postCollected
});
that.showToast(postsCollected, postCollected);
}
},
});
},
showToast: function (postsCollected, postCollected) {
wx.showToast({
// 使用三元表達(dá)式來判斷狀態(tài)
title: postCollected ? '收藏成功!' : '取消成功!',
// 設(shè)置圖標(biāo)停留的時(shí)間,單位是毫秒
duration: 1000,
// icon可以設(shè)置圖標(biāo),默認(rèn)就是success
icon: "success",
});
},
onShareTap: function (event) {
var itemList = [
"分享給微信好友",
"分享到朋友圈",
"分享到QQ",
"分享到微博",
]
wx.showActionSheet({
itemList: itemList,
itemColor: "#405f80",
success: function (res) {
//res.cancel 用戶是否點(diǎn)擊了取消按鈕
//res.tapIndex 數(shù)組元素的索引
wx.showModal({
title: itemList[res.tapIndex],
content: '現(xiàn)在無法實(shí)現(xiàn)分享功能,什么時(shí)候能支持還未知',
})
},
})
},
onMusicTap: function (event) {
var currentPostId = this.data.currentPostId;
var postData = postsData.postList[currentPostId];
// 使用變量來記錄音樂的狀態(tài)
var isPlayingMusic = this.data.isPlayingMusic;
if (isPlayingMusic) {
// 暫停音樂
wx.pauseBackgroundAudio();
this.setData({
isPlayingMusic : false
});
} else {
wx.playBackgroundAudio({
// 流媒體文件的URL,目前支持的格式有 m4a, aac, mp3, wav
dataUrl: postData.music.url,
// 音樂標(biāo)題
title: postData.music.title,
// 音樂封面URL
coverImgUrl: postData.music.coverImg,
});
this.setData({
isPlayingMusic: true
});
}
},
})
以上就算是完成了一個(gè)基本的音樂播放效果,這個(gè)文章詳情頁面也就是算是完成了,雖然我感覺可能還存在一些問題,畢竟沒有完美的代碼,如果后續(xù)出現(xiàn)問題后再進(jìn)行修復(fù)。我個(gè)人覺得開發(fā)項(xiàng)目應(yīng)該先開發(fā)出一個(gè)能夠上線運(yùn)行的原型,在運(yùn)營的過程中再逐步去修復(fù)bug,迭代版本。
在小程序中的緩存數(shù)據(jù)都是沒有時(shí)效期的,不主動清除的話就會一直存在,在模擬器上我們可以點(diǎn)擊工具提供的清除緩存按鈕清除緩存數(shù)據(jù):
但是如果在真機(jī)上,則需要自己手動編寫一個(gè)清除緩存的按鈕,需要使用到wx.clearStorageSync()或wx.clearStorage()方法,前者是同步通清理本地?cái)?shù)據(jù)緩存,后者則是異步清理本地?cái)?shù)據(jù)緩存。當(dāng)點(diǎn)擊這個(gè)按鈕的時(shí)候就能觸發(fā)一個(gè)點(diǎn)擊事件去執(zhí)行這個(gè)清除緩存的方法。
template的路徑問題:
我們都知道template文件中的代碼目的是為了給其他頁面文件復(fù)用的,所以template代碼中的所包含的文件路徑不要寫相對路徑,寫絕對路徑比較好,因?yàn)槿绻募嗀引用了template文件中的代碼,但是文件A和template文件并不是同一級的,那么這時(shí)候如果使用相對路徑就會有問題。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。