前言
项目描述:
本项目的灵感来源于知乎APP和朵朵校友圈微信小程序,ZUCC的同学们在朵朵上分享校园日常等,那么可不可以按照知乎的模式,设计一个
属于ZUCC的专业知识相关的问答平台,但全校范围过广,于是我设计为我们基于我们计算学院的平台,也就是计算机相关专业知识的交流问答平台,这就是
码乎。今天,你码了吗?
本项目只是一个简单的微信小程序demo,使用微信小程序云开发,数据存储在数据库中。
设计思路:
1.完成全局配置,如顶部栏,底部tabBar,将计划中的5个基本页面形成大致框架,并引入所需素材。
2.首先在数据库存入所需数据,相应页面js文件引入data,然后逐个完成页面的排版布局,使页面完整。
3.完成基本交互,包括页面间的跳转,点击事件等。
4.整理代码,修改、弥补不足。
开发工具及环境:
微信开发者工具、VSCode
项目基本页面演示
(本博文所有图片均来自于真机调试)
全局配置
全局JOSN文件 app.jons
全局配置主要用于控制小程序页面以外的内容,如头部和底部导航栏的样式结构等,也决定了整个小程序的内容页数,我们在开始做一个小程序之前,应该先设计好大概的需要做的页面内容,制定好框架再进行,不然在做的过程中容易混乱,想加想改可能都会遇到麻烦。
pages:共5个基本页面,index(首页),answer(回答页),question(问题页),notify(消息页),my(个人页)
"pages":[
"pages/index/index",
"pages/answer/answer",
"pages/notify/notify",
"pages/question/question",
"pages/my/my",
"pages/logs/logs"
]
window:定义小程序所有页面的顶部背景颜色,文字颜色定义等
"window":{
"backgroundTextStyle":"dark",
"navigationBarBackgroundColor": "#0068C4",
"navigationBarTitleText": "码乎",
"navigationBarTextStyle":"white",
"enablePullDownRefresh": true
}
tabBar:底部导航栏组件,控制小程序底部导航栏的所有样式
"tabBar": {
"color": "#aaa",
"selectedColor": "#0068C4",
"backgroundColor": "#ffffff",
"position": "bottom",
"borderStyle": "white",
"list": [
{
"text": "首页",
"pagePath": "pages/index/index",
"iconPath": "images/tabBar/index.png",
"selectedIconPath": "images/tabBar/index_focus.png"
},
{
"text": "消息",
"pagePath": "pages/notify/notify",
"iconPath": "images/tabBar/ring.png",
"selectedIconPath": "images/tabBar/ring_focus.png"
},
{
"text": "我的",
"pagePath": "pages/my/my",
"iconPath": "images/tabBar/my.png",
"selectedIconPath": "images/tabBar/my_focus.png"
}
]
}
全局js文件 app.js
下面的js代码为微信开发者工具原生自带,主要用于授权后获得微信用户信息,这点直接决定了后台数据的调用,数据库的一般分配给每个用户一个单独的id来调取数据,所以这个功能非常重要。在本小程序中,该功能从微信端简单调用登录用户的头像和名字等信息。
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
}
})
// 获取用户信息
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
wx.getUserInfo({
success: res => {
// 可以将 res 发送给后台解码出 unionId
this.globalData.userInfo = res.userInfo
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
if (this.userInfoReadyCallback) {
this.userInfoReadyCallback(res)
}
}
})
}
}
})
各页面基本介绍
首页
基本局部 index.wxml
<!-- 头部搜索框 -->
<view class="search flex-wrp">
<view class="search-left flex-item">
<image src="../../images/search.png"></image>
<input placeholder="搜索ZUCC码乎内容" placeholder-class="search-placeholder" />
</view>
<view class="search-right flex-item">
<image src="../../images/lighting.png"></image>
</view>
</view>
<!-- 用于解决头部被遮挡问题 -->
<view class="vis-wrap">
<view class="vis"></view>
</view>
<!-- 首页列表 -->
<view class="show-list" wx:for="{{feed}}" wx:key="index">
<!-- block01 -->
<view class="list-head" bindtap="toQuestion">
<text class="question">{{item.question}}</text>
</view>
<!-- block02 -->
<view class="user-left">
<image src="{{item.feed_source_img}}"></image>
<text class="name">{{item.feed_source_name}}</text>
</view>
<!-- block03 -->
<view class="answer" bindtap="toAnswer">
<text>{{item.answer_ctnt}}</text>
</view>
<!-- block04 -->
<view class="list-bottom">
<text>{{item.good_num + "赞同 • " + item.comment_num + "评论"}}</text>
<image src="../../images/more.png"></image>
</view>
</view>
</view>
index.js 存放本地数据和跳转功能。wx.navigateTo是非常重要的一个方法,用于页面间的跳转,在页面内多设置跳转,可以提高小程序的交互性。
// 跳转至回答页面
toAnswer: function () {
wx.navigateTo({
url: "../answer/answer"
});
},
//跳转至问题页面
toQuestion: function () {
wx.navigateTo({
url: "../question/question"
});
}
回答页
本页除了基本的样式排版外,实现了关注与取消关注,赞同与取消赞同,收藏与取消收藏功能,下面为演示gif(25s)
以关注和取消关注为例,只需要在data数据中设置一个用于判断当前关注状态的值isFocus,再给收藏标签设置一个bindtap,使之获得一个点击响应方法,该方法通过对当前的isFocus进行判断,从而改变关注标签的样式等。将isFocus保存在数据库,每次加载时即可调取上次保存的关注状态。
下面的收藏功能的部分js代码
focus: function (options) {
console.log(options)
let that = this;
let isFocus = this.data.feed[0].isFocus;
if (!isFocus) { //关注
DB.doc("d6b130aa5fa2c865000c045b41a8468c").update({
data: {
isFocus: true,
focus_text: "已关注",
},
success(res) {
console.log("更新成功", res)
},
fail(res) {
console.log("更新失败", res)
}
})
wx.showToast({
title: '关注成功',
icon: 'none'
})
}
else{ //取消关注
DB.doc("d6b130aa5fa2c865000c045b41a8468c").update({
data: {
isFocus: false,
focus_text: "关注"
},
success(res) {
console.log("更新成功", res)
},
fail(res) {
console.log("更新失败", res)
}
})
wx.showToast({
title: '已取消关注',
icon: 'none'
})
}
问题页
一个朴实无华的问题页。这一页我完全模仿知乎APP的布局排版来设置,非常有意思,最终做出的效果还不错。做这种页面布局很有意义,从最外层一层一层往里挖掘,既需要细心,更需要大局观。
消息页
本页采用顶部栏切换形式,分为动态和消息两栏。实现方法为在js中设置一个判断值currentNavTab,通过点击事件SwitchTab得到当前用户选择的页面,然后修改判断值,通过判断值将另外的页面设置为hidden即可,同时,为了改变顶部栏的样式,也需要通过判断值修改顶部栏的class。
这个在同一页面内的扩展方式也非常常用,很好地将两个息息相关的页面放在同一个大页中,让用户获得良好的体验。
基本布局:
<!-- 顶部导航条 -->
<view class="top-tab">
<view class="toptab {{currentNavtab==idx ? 'active' : ''}}" wx:for="{{navTab}}"
wx:for-index="idx" wx:for-item="itemName" data-idx="{{idx}}" bindtap="switchTab">
{{itemName}}
</view>
</view>
<view class="container">
<!-- 动态栏 -->
<view class="cnt0" hidden="{{currentNavtab==0 ? '' : true}}" wx:for="{{feed}}"
wx:key="{{index}}">
<view class="head">
<view class="img">
<image src="{{item.feed_source_img}}"></image>
</view>
<view class="text">
<text class="name">{{item.feed_source_name}}</text>
<text class="time" decode>收藏了回答 · 10/15</text>
</view>
</view>
<view class="content">
<view class="text">
<view class="title">
<text>{{item.question}}</text>
</view>
<view class="info">
<text decode>{{item.feed_source_name + "的文章 · " + item.good_num
+ " 赞同 · " + item.comment_num + " 评论"}}</text>
</view>
</view>
<view class="img">
<image src="{{item.feed_source_img2}}"></image>
</view>
</view>
</view>
<!-- 消息栏 -->
<view class="cnt1" hidden="{{currentNavtab==1 ? '' : true}}">
<view class="allread">
<view class="list">
<text>消息列表</text>
</view>
<view class="txt">
<text>全部已读</text>
</view>
</view>
<view class="notifylist" wx:for="{{notifyList}}" wx:key="{{index}}">
<view class="img">
<image src="{{item.img}}"></image>
</view>
<view class="info">
<view class="name">
<text>{{item.name}}</text>
</view>
<view class="text">
<text>{{item.text}}</text>
</view>
</view>
<view class="time">
<view>
<text>{{item.time}}</text>
</view>
</view>
</view>
</view>
</view>
js方法:
switchTab: function(e){
this.setData({ //修改判断值,从而改变样式
currentNavtab: e.currentTarget.dataset.idx
});
}
我的页
本页便采用了微信小程序自带的微信授权功能,实现用户信息的交互功能,可在页面中直接展示用户的微信头像及用户昵称,js代码已在前面展示
my.wxml
<view class="container">
<view class="userinfo">
<button class="btn" wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo"
bindgetuserinfo="getUserInfo"> 微信授权登录 </button>
<view wx:else class="content">
<view class="img">
<image bindtap="bindViewTap" class="userinfo-avatar"
src="{{userInfo.avatarUrl}}" mode="cover"></image>
</view>
<view class="text">
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
<text class="setting" decode>个人主页 ></text>
</view>
</view>
</view>
<view class="mylist" wx:for="{{myList}}" wx:key="{{index}}">
<view class="idx">
<view class="img">
<image src="{{item.img}}"></image>
</view>
<view class="text">
<text>{{item.text}}</text>
</view>
</view>
</view>
</view>
问题与发现
1.最大的问题是功能还不完善,本demo只能做展示使用,而没有用户进行提问和回答等功能,有待开发.
2.我在首页做一个顶部固定的(用position:fix实现)的搜索框,然后我还想获得下拉刷新,那么搜索框下面的内容就会被覆盖起来,如果给下面的内容加一个margin-top,那么下拉刷新的白条就会变长,很难看,体验不佳,查了很多资料也没有得到解决方法,只好取消下拉刷新,而顶部固定的内容也有类似情况。
3.做项目时CSS代码非常重要,首先在布局上,总体一般使用flex布局会比较方便,很多时候调整位置会用到相对定位。由于flex布局的通用性和复用性,最好可以将css代码统一写到app.wxss中,那么就可以进行复用,不用再多次地敲重复的代码,很多其他的css样式也是同样的道理。我做这样一个简单的小程序就觉得重复率很高,更何况接下来体量大得多的大作业?很重要的一点,就是提前准备好全局的css代码,在项目前期完善这方面的功能和内容,将会为后面节省下大量的时间和精力,整个项目和代码的结构框架也更清晰,何乐而不为呢?
4.与第二点类似的,微信小程序为我们提供了一个很方便的component,可以用来自定义一些复用组件,也是很好地提高我们写小程序的效率,如果我们能充分利用,会非常有益。
5.软件工程项目需要面向客户,所以交互是非常重要的,而决定交互的一是界面的样式,这是由html和css决定的,而更重要的是小程序对用户操作的反应,这就是由js决定的了,可以说用好js才能做出出色的,功能可靠完全的小程序,因此对于js的学习应该加紧,特别是es6语法,能很大地提高写代码的水准。