微信小程序|开发实战篇之四

前言

实战篇内容参考:
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/my@bg.png" 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布局,非主轴上居中。
  • 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),aboutflex row布局,非主轴居中,主轴两端对齐。PS:这里是我没分析出来的about布局细节。首先about这里也是一个绝对布局,设置一个合适的width:550rpx,设置一下padding上下0,左右100rpx。top也要设置一下。
  • container中是一个like布局,该like布局包含一个image和view。like布局是flex column,非主轴居中,背景颜色设置为#f5f5f5
  • container外部有一个image,position设置为绝对布局。设置width和height,还有topright让其位于右上方。

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
      },{})
    }

  }
})

 var typeText = {100: "电影",200: "音乐",300: "句子"}[newVal.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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值