零基础玩转小程序—吃了么

649 阅读6分钟

前言

不知道大家有没有这种困惑,每次一到饭点就不知道吃什么。小编就是这种情况。每次一到饭点,打开某团某蓝色软件,一看就是半个多小时,最后还不知道吃什么。这就激发了小编想做款美食类App的想法,一打开软件就是别人分享的各种美食图片,再也不用想不到吃什么了。
但由于我刚学小程序半个多月,自身能力比较有限,有些功能还没有完善,只做了登录页面,用户信息页,添加内容,美食展示、搜索以及详情页。下面就由我来介绍下已经实现了的功能吧。

1. 项目预览

1.1 项目构建图

1.2 项目实现界面

2. 实现

2.1 数据库设计

打开云开发建立food数据库

字段CollectionNumdetailgoodimguseruserimg
含义收藏数量文字描述点赞数文字配图用户名用户头像

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. 总结

因为没学多久,小程序这方面的知识掌握的比较少,刚刚开始根本无所下手,后面就开始把项目细化到每一个功能每一个小点,先一个功能一个功能实现,不会就去微信官方文档搜,还没有思路的话,就去百度看看别人是怎么写的,之后再自己捋一遍。
在这项目次实战经验中,学会了几个知识点:

  1. tabbar标签跳转

  2. 获取用户信息

  3. 上传本地图片

  4. 数据库的基本使用,比如增加、修改、更新、获取、查找数据。

  5. 页面和组件或者页面和页面之间的传值

  6. swiper组件应用