前言
不知道大家有没有这种困惑,每次一到饭点就不知道吃什么。小编就是这种情况。每次一到饭点,打开某团某蓝色软件,一看就是半个多小时,最后还不知道吃什么。这就激发了小编想做款美食类App的想法,一打开软件就是别人分享的各种美食图片,再也不用想不到吃什么了。
但由于我刚学小程序半个多月,自身能力比较有限,有些功能还没有完善,只做了登录页面,用户信息页,添加内容,美食展示、搜索以及详情页。下面就由我来介绍下已经实现了的功能吧。
1. 项目预览
1.1 项目构建图
1.2 项目实现界面
2. 实现
2.1 数据库设计
打开云开发建立food数据库
字段 | CollectionNum | detail | good | img | user | userimg |
---|---|---|---|---|---|---|
含义 | 收藏数量 | 文字描述 | 点赞数 | 文字配图 | 用户名 | 用户头像 |
2.2 tabBar跳转
在app.json中添加以下代码,底部栏图标可以去www.iconfont.cn/home/index 中下载
"tabBar": {
"selectedColor": "#000000",
"color": "#808080",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"selectedIconPath": "images/tabBar/index-2.png",
"iconPath": "images/tabBar/index-1.png"
},
{
"pagePath": "pages/add/add",
"text": "添加",
"selectedIconPath": "images/tabBar/add-1.png",
"iconPath": "images/tabBar/add-2.png"
},
{
"pagePath": "pages/user/user",
"text": "用户",
"selectedIconPath": "images/tabBar/user-2.png",
"iconPath": "images/tabBar/user-1.png"
}
]
},
实现结果如图:
2.3用户界面
2.3.1 用户登录界面
1. 我们先设计登录页面获取用户数库,isHide为true,显示登录页面,等用户点击授权后,isHide为false时,才会显示用户信息页
//user.js
Page({
data: {
isHide:false,//判断是否授权
canIuse :wx.canIUse('button.open-type.getUserinfo'),
value:[],
},
onLoad: function () {
var that=this;
//查看是否授权
wx.getSetting({
success:function(res){
if(res.authSetting["scope.userInfo"]){
//authSetting用户授权结果 scope 需要获取权限的
wx.getUserInfo({
success:function(res){
wx.login({
success:res =>{}
});
}
});
} else {//用户没有授权 改变ishide 显示授权页面
that.setData({
isHide:true
});
}
}
});
},
bindGetUserInfo:function(e){
if(e.detail.userInfo) //userInfo用户信息对象
{
var that=this;
console.log("用户信息如下:")
console.log(e.detail.userInfo);
that.setData({//授权成功 通过改变isHide的值 让页面显示出来
isHide:false
});
}else{
wx.showModal({
title: '警告',
content:'你点击了拒绝授权 将无法进入小程序 请授权后在进入',
showCancel:false,
success:function(res){
if(res.confirm){
console.log('用户点击了返回授权');
}
}
})
}
},
实现页面如下
2.3.2 用户显示页面
直接用open-data展示微信开放的数据。open-data详细文档developers.weixin.qq.com/miniprogram…
<view class="userpage" wx:if="{{!isHide}}" >
<view class="userinfo">
<view class="userimg">
<open-data type="userAvatarUrl"></open-data>
</view>
<view class="username">
<open-data type="userNickName"></open-data>
</view>
</view>
<view class="info">
</view>
</view>
2.4 添加内容上传到云数据库
1. 选择图片上传
//上传图片功能
uploadimg:function(){
wx.chooseImage({
count: 9,
sizeType:['original','compressed'],
sourceType:['album','camera'],
success:res=>{
const filepaths =res.tempFilePaths
this.setData({
tempImg:filepaths,
// isupload:true
})
}
})
},
2. 获取输入内容
upcontent:function(e){
this.setData({
content:e.detail.value
})
},
3. 点击提交按钮,将内容添加到云数据库
//提交按钮
submit:function(e){
wx.showLoading({
title: '提交中',
})
const arr=[]
for(let i=0; i<this.data.tempImg.length;i++){
let filepath =this.data.tempImg[i]
let all = /\.[^\.]+$/.exec(filepath)[0]; //查找图片后缀格式
arr.push(new Promise((reslove,reject)=>{
// Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息。
wx.cloud.uploadFile({
cloudPath:new Date().getTime()+all, // cloudPath云存储路径
filePath:filepath, //filePath要上传文件资源的路径 (本地路径)
}).then(res=>{
console.log(res.fileID) //Promise返回结果说明fileID 文件ID
this.setData({
fileIDs:this.data.fileIDs.concat(res.fileID)
}) //concat() 方法用于连接两个或多个数组。
reslove()
}).catch(error=>{
console.log(error)
})
}))
}
//将信息传送到数据库
Promise.all(arr).then(res=>{
db.collection('food').add({
data:{
img:this.data.fileIDs,
detail:this.data.content,
user:this.data.name,
userimg:this.data.img,
time:new Date(),
good:0,
CollectionNum:0,
}
})
}).then(res=>{
wx.hideLoading()
wx.showToast({
title: '提交成功',
})
this.setData({
content:[],
tempImg:[]
})
}).catch(error=>{
console.log(error)
})
},
2.5 首页设计
2.5.1 搜索栏
1.在miniprogram\components中新建search组件,方便引入
search.wxml代码
<view class="search-bar">
<view class="search-bar-box">
<icon class="search-bar-img" type="search" size="14"></icon>
<input class="search-bar-input" type="text" placeholder="请输入搜索内容" bindblur="getword" value="{{value}}"/>
</view>
<view class="search-bar-btn" bindtap='searchword'>
搜索
</view>
</view>
要记得在index.json中引入组件
"usingComponents": {"search-bar": "/components/search/search"}
2.5.2 轮播图
同样在miniprogram\components中新建swiperimg组件
1. 首先在index.js的data中设置要传送的imgUrls
data: {
imgUrls: [
'../../images/swiper/1.jpg',
'../../images/swiper/2.jpg',
],
},
2. 在swiperimg.js中定义imgUrls参数接受父类传送的轮播图地址
properties: {
imgUrls:Object,
},
3. swiper.wxml代码
<!-- 自动切换 自动切换时间间隔 滑动动画时长 衔接滑动 衔接滑动-->
<view class="swiperContainer">
<swiper class="swiper-box" autoplay="true" interval="5000" duration="1000" circular="true" indicator-dots="true" >
<block wx:for="{{imgUrls}}" wx:key="index">
<swiper-item>
<image src="{{item}}" class="slide-image" mode="aspectFill"/>
</swiper-item>
</block>
</swiper>
</view>
4. 同样也记得在index.json首页引入
"usingComponents": {
"index-swiper": "/components/swiperimg/swiperimg",
"search-bar": "/components/search/search"
<!-- index.wxml -->
<view class="swiper-container">
<index-swiper imgUrls="{{imgUrls}}"> </index-swiper>
</view>
好啦,到这为止,轮播图就做好了,让我们来看看效果吧。(淋上甜甜蜂蜜的华夫饼,加上绵密的冰淇淋和甜甜的草莓。我现在想!!!立刻!!!马上!!!出去吃!!!! )
2.5.3 美食展示
1. 在index.js中从数据库中获取数据,按时间排序
onLoad: function (e) {
let that =this
wx.cloud.database().collection("food").orderBy('time','desc').get({
success(res){
that.setData({
imgList:res.data//将获取到的数据传给imglist列表
})
}
})
},
2. index.wxml中描述页面结构
<view class="container">
<block wx:for="{{imgList}}">
<view class="food" bindtap="onDetail" data-id="{{item._id}}">
<!-- 借助 data-* 属性进行标示-->
<view class="i">
<image src="{{item.img[0]}}" mode="aspectFill"> </image>
</view>
<text class="words">{{item.detail}}</text>
</view>
</block>
</view>
实现页面展示:
2.6 详情页
1. 跳转详情页,在index.js中设置点击函数,将获取到的id传送给详情页
onDetail: function (e) {
var foodurl = e.currentTarget.dataset.id;
//currentTarget 事件属性返回其监听器触发事件的节点
wx.navigateTo({
url: "../detail/detail?id=" + foodurl,
})
},
2.新建一个详情页detail的page页面,在detail.js中捕捉index.js传送过来的参数id,之后在数据库中搜寻
onLoad: function (e) {
let that=this
let a=e.id
wx.cloud.database().collection("food").where({
_id:a
}).get({
success(res){
that.setData({
all:res.data,
img:res.data[0].img,
user:res.data[0].user,
userimg:res.data[0].userimg,
detail:res.data[0].detail,
goodnum:res.data[0].good,
colnum:res.data[0].CollectionNum,
})
}
})
},
3. 详情页展示,详情页的图片展示使用轮播图方式,记得引入轮播图组件
<!--miniprogram/pages/detail/detail.wxml-->
<!--图片展示-->
<view class="container">
<view class="img-swiper">
<index-swiper imgUrls="{{img}}" mode="aspectFill"> </index-swiper>
</view>
<!--用户头像、用户名、用户发表的文章内容-->
<view class="user-info">
<image src="{{userimg}}" mode="aspectFill"></image>
<text class ="user">{{user}}</text>
</view>
<view class="food">
<text class="words">{{detail}}</text>
</view>
</view>
<!--收藏、点赞、评论、-->
<view class="bottom" wx:for="{{all}}">
<view class='collection' bindtap='colbtn' data-id="{{item._id}}">
<image wx:if="{{colstatus}}" src="../../images/detail/collection.png" mode='aspectFill'></image>
<image wx:else src="../../images/detail/collection2.png" mode="aspectFill"></image>
<text>{{colnum}}</text>
</view>
<view class='good' bindtap='goodbtn' data-id="{{item._id}}">
<image wx:if="{{goodstatus}}" src="../../images/detail/good.png" mode='aspectFill'></image>
<image wx:else src="../../images/detail/good2.png" mode='aspectFill'></image>
<text>{{goodnum}}</text>
</view>
<view class='comment' bindtap='comment' data-id="{{item._id}}">
<image src="../../images/detail/comment.png" mode='aspectFill'></image>
<text></text>
</view>
</view>
3. 详情页点赞功能 在data中设置数据goodstatus初始值为true,第一次点击时,goodstatus为true,点赞数加1,向数据库发送数据,goodstatu改变值为false。第二次点击时,goodstatus为false,点赞被取消,向数据库发送数据。收藏功能和点赞代码一样,我就不展示收藏功能代码了
//点赞
goodbtn:function(e){
// 判断是否点赞过
if(this.data.goodstatus==true){
this.setData({
goodstatus:false,
goodnum:this.data.goodnum+1
})
}else if(this.data.goodstatus==false){
this.setData({
goodstatus:true,
goodnum:this.data.goodnum-1
})
}
// console.log(this.data.goodnum)
//数值更新数据库
const db=wx.cloud.database()
console.log(e.currentTarget.dataset.id)
db.collection('food').doc(
e.currentTarget.dataset.id
).update({
// data 传入需要局部更新的数据
data: {
good:this.data.goodnum
},
success: res => {
}
})
},
页面展示:
2.7 搜索结果展示
1. 在index.wxml中引入search组件,在index.js中获取到search组件传送过来的搜索数据,将其传送给新建的search-page页面
<!-- index.wxml -->
<!-- 导航栏 -->
<view class="search">
<search-bar bindsearchwords="searchwords" >
</search-bar>
</view>
//index.js
searchwords(e){
this.setData({
values:e.detail
})
wx.navigateTo({
url: "../search-page/search?word=" +this.data.values,
})
},
2. 新建search-page的page页面,用来展示搜索结果,search-page.js接受index.js传送的数据,之后在数据库中进行搜索
onLoad: function (e) {
let that=this
const db=wx.cloud.database()
db.collection("food").where({
detail: db.RegExp({
regexp: e.word, //搜索首页传过来的数据e.word
options: 'i',
})
})
.orderBy('time','desc').get({
success(res){
that.setData({
all:res.data,
img:res.data[0].img,
user:res.data[0].user,
userimg:res.data[0].userimg,
detail:res.data[0].detail,
})
}
})
},
3. 在search-page页面上方也引入search组件,使其可以在上方搜索,更加方便
"usingComponents": {"my-search":"/components/search/search"}
<!-- search-page.wxml-->
<view class="seacher">
<my-search bindsearchwords="searchwords">
</my-search>
</view>
//搜索页面数据
searchwords(e){
this.setData({
words:e.detail
})
console.log(this.data.words)
var that=this
const db=wx.cloud.database()
db.collection("food").where({
detail: db.RegExp({
regexp: that.data.words,
options: 'i',
})
})
.orderBy('time','desc').get({
success(res){
that.setData({
all:res.data,
img:res.data[0].img,
user:res.data[0].user,
userimg:res.data[0].userimg,
detail:res.data[0].detail,
})
}
})
},
页面展示
5.search-page获取商品id,跳转详情页
ondetail:function(e){
var id=e.currentTarget.dataset.id
wx.navigateTo({
url: '../detail/detail?id='+id,
})
}
3. 总结
因为没学多久,小程序这方面的知识掌握的比较少,刚刚开始根本无所下手,后面就开始把项目细化到每一个功能每一个小点,先一个功能一个功能实现,不会就去微信官方文档搜,还没有思路的话,就去百度看看别人是怎么写的,之后再自己捋一遍。
在这项目次实战经验中,学会了几个知识点:
-
tabbar标签跳转
-
获取用户信息
-
上传本地图片
-
数据库的基本使用,比如增加、修改、更新、获取、查找数据。
-
页面和组件或者页面和页面之间的传值
-
swiper组件应用