0. 前言
本文将手把手教你如何写出迷你版微博的一行行代码,迷你版微博包含以下功能:
- Feed 流:关注动态、所有动态
- 发送图文动态
- 搜索用户
- 关注系统
- 点赞动态
- 个人主页
使用到的云开发能力:
- 云数据库
- 云存储
- 云函数
- 云调用
没错,几乎是所有的云开发能力。也就是说,读完这篇实战,你就相当于完全入门了云开发!
咳咳,当然,实际上这里只是介绍核心逻辑和重点代码片段,完整代码建议下载查看。
1. 取得授权
作为一个社交平台,首先要做的肯定是经过用户授权,获取用户信息,小程序提供了很方便的接口:
<button open-type="getUserInfo" bindgetuserinfo="getUserInfo">
进入小圈圈
</button>
这个 button
有个 open-type
属性,这个属性是专门用来使用小程序的开放能力的,而 getUserInfo
则表示 获取用户信息,可以从bindgetuserinfo
回调中获取到用户信息。
于是我们可以在 wxml 里放入这个 button
后,在相应的 js 里写如下代码:
Page({
...
getUserInfo: function(e) {
wx.navigateTo({
url: "/pages/circle/circle"
})
},
...
})
这样在成功获取到用户信息后,我们就能跳转到迷你微博页面了。
需要注意,不能使用 wx.authorize({scope: "scope.userInfo"})
来获取读取用户信息的权限,因为它不会跳出授权弹窗。目前只能使用上面所述的方式实现。
2. 主页设计
社交平台的主页大同小异,主要由三个部分组成:
- Feed 流
- 消息
- 个人信息
那么很容易就能想到这样的布局(注意新建一个 Page 哦,路径:pages/circle/circle.wxml
):
<view class="circle-container">
<view
style="display:{
{
currentPage === 'main' ? 'block' : 'none'}}"
class="main-area"
>
</view>
<view
style="display:{
{
currentPage === 'msg' ? 'flex' : 'none'}}"
class="msg-area"
>
</view>
<view
style="display:{
{
currentPage === 'me' ? 'flex' : 'none'}}"
class="me-area"
>
</view>
<view class="footer">
<view class="footer-item">
<button
class="footer-btn"
bindtap="onPageMainTap"
style="background: {
{
currentPage === 'main' ? '#111' : 'rgba(0,0,0,0)'}}; color: {
{
currentPage === 'main' ? '#fff' : '#000'}}"
>
首页
</button>
</view>
<view class="footer-item">
<button
class="footer-btn"
bindtap="onPageMsgTap"
style="background: {
{
currentPage === 'msg' ? '#111' : 'rgba(0,0,0,0)'}}; color: {
{
currentPage === 'msg' ? '#fff' : '#000'}}"
>
消息
</button>
</view>
<view class="footer-item">
<button
class="footer-btn"
bindtap="onPageMeTap"
style="background: {
{
currentPage === 'me' ? '#111' : 'rgba(0,0,0,0)'}}; color: {
{
currentPage === 'me' ? '#fff' : '#000'}}"
>
个人
</button>
</view>
</view>
</view>
很好理解,画面主要被分为上下两个部分:上面的部分是主要内容,下面的部分是三个 Tab 组成的 Footer。重点 WXSS 实现(完整的 WXSS 可以下载源码查看):
.footer {
box-shadow: 0 0 15rpx #ccc;
display: flex;
position: fixed;
height: 120rpx;
bottom: 0;
width: 100%;
flex-direction: row;
justify-content: center;
z-index: 100;
background: #fff;
}
.footer-item {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
width: 33.33%;
color: #333;
}
.footer-item:nth-child(2) {
border-left: 3rpx solid #aaa;
border-right: 3rpx solid #aaa;
flex-grow: 1;
}
.footer-btn {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
border-radius: 0;
font-size: 30rpx;
}
核心逻辑是通过 position: fixed
来让 Footer 一直在下方。
读者会发现有一个 currentPage
的 data ,这个 data 的作用其实很直观:通过判断它的值是 main
/msg
/me
中的哪一个来决定主要内容。同时,为了让首次使用的用户知道自己在哪个 Tab,Footer 中相应的 button
也会从白底黑字黑底白字,与另外两个 Tab 形成对比。
现在我们来看看 main
部分的代码(在上面代码的基础上扩充):
...
<view
class="main-header"
style="display:{
{
currentPage === 'main' ? 'flex' : 'none'}};max-height:{
{
mainHeaderMaxHeight}}"
>
<view class="group-picker-wrapper">
<picker
bindchange="bindGroupPickerChange"
value="{
{groupArrayIndex}}"
range="{
{groupArray}}"
class="group-picker"
>
<button class="group-picker-inner">
{
{groupArray[groupArrayIndex]}}
</button>
</picker>
</view>
<view class="search-btn-wrapper">
<button class="search-btn" bindtap="onSearchTap">搜索用户</button>
</view>
</view>
<view
class="main-area"
style="display:{
{
currentPage === 'main' ? 'block' : 'none'}};height: {
{
mainAreaHeight}};margin-top:{
{
mainAreaMarginTop}}"
>
<scroll-view scroll-y class="main-area-scroll" bindscroll="onMainPageScroll">
<block
wx:for="{
{pageMainData}}"
wx:for-index="idx"
wx:for-item="itemName"
wx:key="_id"
>
<post-item is="post-item" data="{
{itemName}}" class="post-item-wrapper" />
</block>
<view wx:if="{
{pageMainData.length === 0}}" class="item-placeholder"
>无数据</view
>
</scroll-view>
<button
class="add-poster-btn"
bindtap="onAddPosterTap"
hover-class="add-poster-btn-hover"
style<