天天看點

微信小程式|開發實戰篇之四前言1、使用者頁面my的開發2、image-button元件的開發3、preview元件的開發

開發實戰篇之四

  • 前言
  • 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、使用者頁面my的開發2、image-button元件的開發3、preview元件的開發

1.2.1 從原型頁面來分析:

  • 首先整個頁面處于大的

    container

    布局之下,

    container

    應該是

    flex column

    布局,非主軸上居中。
  • container

    中是一張image,需設定height、width。
  • container

    中包含一個

    image-button

    元件,一個

    view

    元件(授權之後顯示的view,包含一個image和text),由

    properties

    中的

    authorized

    的true or false來wx:if渲染與否。

    image-button

    元件的

    position

    設定為絕對布局,設定top屬性即可。當授權之後顯示view,view的布局為

    flex column

    ,非主軸都居中對齊。
  • container

    中接下來是一個

    about

    布局,該

    about

    布局包含view(一個内部是image和text,另一個兩個text),

    about

    flex row

    布局,非主軸居中,主軸兩端對齊。PS:這裡是我沒分析出來的about布局細節。首先about這裡也是一個絕對布局,設定一個合适的width:550rpx,設定一下padding上下0,左右100rpx。top也要設定一下。
  • container

    中是一個

    like

    布局,該

    like

    布局包含一個image和view。

    like

    布局是

    flex column

    ,非主軸居中,背景顔色設定為

    #f5f5f5

  • container

    外部有一個image,

    position

    設定為絕對布局。設定width和height,還有

    top

    right

    讓其位于右上方。

1.2.2 繼續分析每個大元件中的小元件布局:

  • about

    布局中的兩塊view元件,各自都是

    flex column

    布局,非主軸居中對齊,主軸兩端對齊,設為不靠的太近即可。
  • like

    布局中包括一個image,需要設定headline樣式:width和height,

    margin-top

    距離上邊距離。然後是顯示喜歡書籍的縮略圖的

    preview-container

    布局,是一個

    flex row

    布局,主軸兩端對齊,設定

    margin-top

    距離上部的距離。PS:這裡是我沒分析出來的like布局細節。首先要設定一個合适的width:690rpx,設定一下左右的内邊距,padding上下0,左右30rpx。重要!!! 設定flex-wrap:wrap;讓preview元件之間有空隙!
  • image-button

    顯示的

    image

    需要對頭像的位置及大小進行設定,首先對width、height設定合适rpx,再設定

    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;
}