開發實戰篇之四
- 前言
- 1、使用者頁面my的開發
-
- 1.1 my.wxml骨架檔案
- 1.2 my頁面的布局和樣式分析
-
- 1.2.1 從原型頁面來分析:
- 1.2.2 繼續分析每個大元件中的小元件布局:
- 1.3 my頁面的邏輯代碼分析
- 2、image-button元件的開發
- 3、preview元件的開發
前言
實戰篇内容參考:
1、小程式開發實戰:https://coding.imooc.com/class/chapter/251.html#Anchor
2、部落客:ssc在路上
1、使用者頁面my的開發
使用者my頁面是tar欄第三個按鈕切換的頁面,主要是展示使用者資訊和使用者喜歡的雜志,需要建立兩個新元件,一個是image-button,這個可以用來自定義按鈕樣式和功能,一個是preview元件,這個是用來展示标記為喜歡的書籍的。
1.1 my.wxml骨架檔案
<!--pages/my/my.wxml-->
<view class="container">
<image src="/images/my/[email protected]" class="bg"></image>
<!-- <open-data type="userAvatarUrl" class="avatar avatar-position"></open-data> -->
<!-- 授權 -->
<v-button wx:if="{{!authorized}}"
open-type="getUserInfo" class="avatar-position"
bind:getuserinfo="onGetUserInfo">
<image slot="img" class="avatar"
src="/images/my/my.png" />
</v-button>
<view wx:if="{{authorized}}" class="avatar-container avatar-position">
<image class="avatar"
src="{{userInfo.avatarUrl}}" />
<text>{{userInfo.nickName}}</text>
</view>
<view class="about-container">
<view class="about-us" bind:tap="onJumpToAbout">
<image src="/images/my/about.png"></image>
<text class="description">關于我們</text>
</view>
<view class="about-us">
<text class="book-num">{{bookCount}}</text>
<text class="description">喜歡的書</text>
</view>
</view>
<!-- 喜歡的雜志清單 -->
<view class="like-container">
<!-- 喜歡分割線 -->
<image class="headline" src="/images/my/like.png"></image>
<!-- 喜歡的書籍卡片預覽 -->
<view class="preview-container">
<block wx:for="{{classics}}">
<v-preview bind:tapping="onPreviewTap" class="preview" classic="{{item}}" />
</block>
</view>
</view>
</view>
<image bind:tap="onStudy" class="study" src="/images/my/study.png"></image>
1.2 my頁面的布局和樣式分析
為了熟練界面的開發,還是事無巨細地将整個my頁面分析一下。
1.2.1 從原型頁面來分析:
- 首先整個頁面處于大的
布局之下,container
應該是container
布局,非主軸上居中。flex column
-
中是一張image,需設定height、width。container
-
中包含一個container
元件,一個image-button
元件(授權之後顯示的view,包含一個image和text),由view
中的properties
的true or false來wx:if渲染與否。authorized
元件的image-button
設定為絕對布局,設定top屬性即可。當授權之後顯示view,view的布局為position
,非主軸都居中對齊。flex column
-
中接下來是一個container
布局,該about
布局包含view(一個内部是image和text,另一個兩個text),about
是about
布局,非主軸居中,主軸兩端對齊。PS:這裡是我沒分析出來的about布局細節。首先about這裡也是一個絕對布局,設定一個合适的width:550rpx,設定一下padding上下0,左右100rpx。top也要設定一下。flex row
-
中是一個container
布局,該like
布局包含一個image和view。like
布局是like
,非主軸居中,背景顔色設定為flex column
。#f5f5f5
-
外部有一個image,container
設定為絕對布局。設定width和height,還有position
和top
讓其位于右上方。right
1.2.2 繼續分析每個大元件中的小元件布局:
-
布局中的兩塊view元件,各自都是about
布局,非主軸居中對齊,主軸兩端對齊,設為不靠的太近即可。flex column
-
布局中包括一個image,需要設定headline樣式:width和height,like
距離上邊距離。然後是顯示喜歡書籍的縮略圖的margin-top
布局,是一個preview-container
布局,主軸兩端對齊,設定flex row
距離上部的距離。PS:這裡是我沒分析出來的like布局細節。首先要設定一個合适的width:690rpx,設定一下左右的内邊距,padding上下0,左右30rpx。重要!!! 設定flex-wrap:wrap;讓preview元件之間有空隙!margin-top
-
顯示的image-button
需要對頭像的位置及大小進行設定,首先對width、height設定合适rpx,再設定image
多出來的圖檔隐藏掉,overflow:hidden
設定頭像為圓形才會生效。border-radius:50%
- 對
元件進行設定preview
,讓margin-bottom:30rpx
每個wx:for
元件上下之間空出一段距離。preview
my頁面中使用者資訊的處理:
擷取使用者資訊現在需要使用者自己進行授權,觸發使用者授權的可以使用button,是以封裝了一個自定義按鈕image-button。為提高image-button的通用性使用了slot插槽。
<v-button wx:if="{{!authorized}}"
open-type="getUserInfo" class="avatar-position"
bind:getuserinfo="onGetUserInfo">
<image slot="img" class="avatar"
src="/images/my/my.png" />
</v-button>
點選會觸發onGetUserInfo函數,my.js中:
// 點選授權函數,儲存使用者資訊userInfo
onGetUserInfo(event){
const userInfo = event.detail.userInfo;
if(userInfo){
this.setData({
userInfo,
authorized:true
});
console.log(userInfo);
}
},
1.3 my頁面的邏輯代碼分析
// pages/my/my.js
import {
ClassicModel
} from '../../models/classic.js'
import {
BookModel
} from '../../models/book.js'
const classicModel = new ClassicModel();
const bookModel = new BookModel();
Page({
/**
* 頁面的初始資料
*/
data: {
authorized:false,
userInfo: null,
bookCount: 2,
classics:[{
"content": "人生不能像做菜,把所有的料準備好才下鍋",
"fav_nums": 1,
"id": 1,
"image": "/components/classic/movie/images/movie.jpg",
"pubdate": "2018-06-22",
"title": "李安<<飲食男女>>",
"type": 100
},
{
"content": "你陪我步入蟬夏 越過城市喧嚣",
"fav_nums": 0,
"id": 3,
"image": "/components/classic/movie/images/movie.jpg",
"index": 1,
"like_status": 0,
"pubdate": "2018-06-22",
"title": "紙短情長",
"type": 200,
"url": "http://music.163.com/song/media/outer/url?id=557581284.mp3"
},
{}]
},
/**
* 生命周期函數--監聽頁面加載
*/
onLoad: function (options) {
this.userAuthorized();
this.getMyBookCount();
this.getMyFavor();
},
// 點選跳轉頁面
onPreviewTap(event){
console.log(event);
const cid = event.detail.cid;
const type = event.detail.type
wx.navigateTo({
url: '/pages/index/index',
})
},
// 取得我的喜歡
getMyFavor(){
classicModel.getMyFavor(res=>{
this.setData({
classics:res
})
})
},
// 使用者是否授權
userAuthorized(){
wx.getSetting({
success:data=>{
if(data.authSetting['scope.userInfo']){
wx.getUserInfo({
success:data=>{
this.setData({
authorized:true,
userInfo: data.userInfo
})
}
})
}
}
})
},
// 點選授權函數
onGetUserInfo(event){
const userInfo = event.detail.userInfo;
if(userInfo){
this.setData({
userInfo,
authorized:true
});
console.log(userInfo);
}
},
onJumpToAbout(event){
wx.navigateTo({
url: '/pages/about/about',
})
},
onStudy(event){
wx.navigateTo({
url: '/pages/course/course',
})
},
// 擷取喜歡書的數量
getMyBookCount(event){
bookModel.getMyBookCount()
.then(res =>{
this.setData({
bookCount:res.count
})
})
}
})
- 其中的bookCount表示我喜歡的書籍數量,需要通過BookModel中的getMyBookCount()函數,顯示對應的期刊資訊需要通過ClassicModel中的getMyfavor()函數。是以可以将這兩個函數的調用放到頁面的Load()生命周期函數中。
- 點選授權函數onGetUserInfo(),主要是驗證使用者是否驗證,并且儲存userInfo,對authorized信号量設為true。
- onStudy()函數跳轉到course頁面。
- onJumpToAbout()函數跳轉到about頁面。
- 每個preview點選的響應事件onPreviewTap()攜帶cid和type跳轉到對應期刊界面。
2、image-button元件的開發
image-button元件主要是由一個button元件和一個slot插槽組成。
- open-type代表外部傳入的系統操作類型,例如“
”擷取使用者授權資訊getUserInfo
- plain="{{true}}" 表示按鈕镂空。
- slot添加插槽。
<button bind:getuserinfo="onGetUserInfo"
open-type="{{openType}}" plain='{{true}}' size="mini"
class="container">
<slot name="img"></slot>
</button>
js設定onGetUserInfo()自定義函數,并且開啟多插槽:
/**
* 元件的屬性清單
*/
options: {
multipleSlots: true
},
properties: {
openType: {
type: String
}
},
/**
* 元件的方法清單
*/
methods: {
onGetUserInfo(event){
this.triggerEvent('getuserinfo', event.detail, {})
}
}
wxss樣式:
/* components/image-button/index.wxss */
.container {
/* display: inline-flex; */
padding: 0 !important;
border: none !important;
}
3、preview元件的開發
preview的骨架代碼:
<!--components/preview/index.wxml-->
<view catch:tap="onTap" class="container">
<view class="head">
<v-tag text="{{typeText}}" tag-class="tag" />
<v-like class="like" read-only="{{true}}" like="{{true}}" count="{{classic.fav_nums}}" />
</view>
<image class="{{classic.type==200?'music-img':'other-img'}}" src="{{classic.image}}"></image>
<view class="text">{{classic.content}}</view>
</view>
preview的js邏輯代碼:
// components/preview/index.js
Component({
/**
* 元件的屬性清單
*/
properties: {
classic: {
type: Object,
observer: function(newVal) {
if(newVal){
var typeText = {
100: "電影",
200: "音樂",
300: "句子"
}[newVal.type]
}
this.setData({
typeText: typeText
})
}
}
},
/**
* 元件的初始資料
*/
data: {
typeText: ''
},
/**
* 元件的方法清單
*/
methods: {
onTap:function(event){
this.triggerEvent('tapping',{
cid:this.properties.classic.id,
type:this.properties.classic.type
},{})
}
}
})
這是js文法取數組中對應key的value。
preview的樣式代碼:
/* components/preview/index.wxss */
.container{
display: flex;
flex-direction: column;
align-items: center;
width:330rpx;
background-color: #ffffff;
}
.head{
display: flex;
width:100%;
flex-direction: row;
align-items: center;
justify-content: space-between;
height:80rpx;
}
.tag{
margin-left:20rpx;
margin-top:-2rpx;
height:40rpx;
width:72rpx ;
font-size:24rpx;
background-color:#f7f7f7 !important;
}
.like{
margin-top:4rpx;
margin-right:4rpx;
}
.other-img{
width:100%;
height:240rpx;
}
.music-img{
border-radius: 50%;
width:240rpx;
height:240rpx;
}
.text{
padding:30rpx;
font-size:28rpx;
height:130rpx;
color:#666666;
overflow: hidden;
}