微信小程序-麦当劳点餐+爬虫

4,763 阅读19分钟

hello大家好,这是我的第一篇掘金文章,每天都在掘金上面看各位大佬的文章,终于鼓足勇气决定写一篇属于自己的文章了。今天呢,就给大家带来一篇微信小程序(麦当劳点餐)+爬虫的详解吧。大佬们可以忽略我这个小辣鸡,但是如果你也是前端小白的话,可以认真看看哟,说不定对你有帮助呢。

项目介绍

这个小程序是为最近参加的一个小活动而制作的(为期两天,3-4人组队,完成一个小型项目)。说实话,两天怎么可能完成一个小程序呢?在前两天,我们大致完成了小程序基本结构,然后由我完成收尾工作,前前后后历时四天。

项目预览图

大家可以看到,这个小程序有四个页面。

项目工作分配

由于我是组长,所以工作的内容是由我分配的,我们组内四个成员,正好一人一个页面,但是页面有简单和复杂之分的,在我的暴政下,分到了复杂页面的也不许抱怨!当然我是一个好组长,我给自己分配了选餐的页面并且爬虫爬数据也由我完成。所以下面我给大家分享的就是我完成的那个页面。

项目开始前的准备

一些准备工作:

  • 申请账号:进入微信公众平台根据指示申请注册账号
  • 开发工具:VScode和微信开发者工具
  • 小程序官方文档
  • github申请存储库

使用的一些工具:

  • 小程序云开发数据库功能
  • 微信官方文档
  • markMan(可以进行图片测量和标注的工具)
  • iconfont(阿里巴巴矢量图标库,有大量icon资源)
  • github(由于这是我们一个小组完成的项目,所以需要建一个新的存储库,然后把大家拉进来)

这里需要着重说明一下github命令行的操作,一个人开发的时候,直接git push就行。但是多人合作开发的时候,是不能直接git push的,如果别人先提交了项目,然后你再提交之前一定先要git pull,先把别人的项目拉下来,然后在git push,不然会导致冲突。

其实除了这些基本的准备工作以外,我们最应该做的就是思考。有一位前辈曾经告诉我,在接手项目的时候,不应该第一时间就去敲代码,而是应该闭上眼睛思考一会。具体思考什么,他也没有细说,但是通过这次,我领悟到了前辈的意思。首先,我们需要仔细的看一下设计稿,在脑子里搭建起来大致的框架,以便在写代码的时候,可以提升效率。其次,我们应该思考数据如果存放,打个比方:在做电商页面的时候,点击左边导航栏,右边内容框显示相应的数据,这就涉及到数据的存放了。所以在写代码之前,我们就应该思考好这些逻辑。

项目完成过程

下图就是我要完成的页面。

第一开始看见这个页面的时候,心里其实并不慌,因为之前也做过一些电商的小程序,所以知道这个页面的基本功能应该如何实现,所以在写代码的过程中,还算很顺利。

点餐页面

当看见这个页面的时候,脑子里大致就需要搭建一个结构框架。

  • 页面上端是一个swiper,用于滚动不同的广告。
  • 页面中间的部分是地址栏,点击可以选择不同的商店。
  • 页面中下部是一个点餐栏,左边和右边同时都要使用scroll-view。
  • 尾部是一个类似于购物车的东西,这一部分建议大家写成一个组件调用,为了减少代码耦合度。(虽然我没用组件)

话不多说,下面来分析结构吧!

首先我们来看一下页面的swiper部分

可以从图片看出,这是一个广告位置,用于放置最新的产品,这一部分其实很简单,直接引用小程序的swiper组件即可。

<swiper indicator-dots="true" 
        indicator-active-color="rgba(242,207,4,1)" 
        autoplay="true" 
        circular="true" 
        interval="4000" 
        duration="1000" 
        class="header" 
        wx:if="{{hidden}}">
        <swiper-item wx:for="{{adImage}}" wx:key="index">
            <image mode="aspectFill" class="headerImg" src="{{item.image}}" />
        </swiper-item>
    </swiper>

这一部分代码如上,需要提一下的就是swiper组件里面indicator-active-color这个属性只接受rgba形式,不接受十六进制颜色的输入,大家可以自行在百度上面找转换的方法。

接下来就是地址栏的部分

我这里放两张图片,方便对比:

这一部分的页面并不算简单,首先外面的大盒子需要设置为弹性布局,方便左边的地址栏,还有右边的会员并排在一排。然后地址栏也需要设置为弹性布局,将flex-flow设置为column就可以沿Y轴分布,然后将align-items: center;就可以把店名还有地址放在方框中间。因为这个地址栏是可以点击切换地址的,所以内边距不可以写死,只能用弹性布局将它们放在中间,如果选择的地址过长的话,页面也会自动调整边距,十分的美观。

<!-- 地址栏 -->
    <view class="middle" wx:if="{{hidden}}">
        <navigator style="display: inline-block" target="" url="../index/index" hover-class="navigator-hover">
            <view class="address">
                <view>
                    <view class="storeName">{{storeInfo.name}}</view>
                    <view class="storeAdress">{{storeInfo.address}}</view>
                </view>
            </view>
        </navigator>
        <view class="member">
            <image src="../../images/menuImg/u=324093054,273186418&fm=26&gp=0.jpg" class="menberImg" />
            <text class="memberText">会员中心</text>
        </view>
    </view>
.middle{
    height: 110rpx;
    width: 100%;
    background-color: #fff;
    display: flex;
    border-bottom: 1px solid #eeeeee;
}
.address{
    width: 600rpx;
    height: 110rpx;
    display: flex;
    align-items: center;
    border-right: 1px solid #eeeeee;
}
.storeName{
    line-height: 40rpx;
    font-size: 28rpx;
    font-weight: bold;
    margin-left: 40rpx;
}
.storeAdress{
    line-height: 34rpx;
    font-size: 22rpx;
    color: #737373;
    margin: 0 40rpx;
}
.member{
    width: 150rpx;
    height: 110rpx;
    padding: 16rpx 0;
    box-sizing: border-box;
    display: flex;
    flex-flow: column;
    align-items: center;
}
.menberImg{
    width: 40rpx;
    height: 40rpx;
    border-radius: 50%;
    margin: 0 ;
}
.memberText{
    position: relative;
    width: 100%;
    font-size: 24rpx;
    line-height: 24rpx;
    text-align: center;
    margin-top: 14rpx;
}

因为这里是有一个点击事件的,点击过后,跳转到选地址页面,然后选完地址在跳转回本页面。那么在页面与页面之间是怎么传递数据的呢?在逛了一圈小程序开发文档之后,我们发现了一个api十分的好用,可以将页面的数据暂时放入缓存区,以一个key来命名,然后在另外一个页面,也用相同的key来获取,就可以获取缓存区的数据了,下面来看看代码吧。

toDetail (e) {
    let idx = e.currentTarget.dataset.idx;
    if (idx) {
      wx.setStorage({
        key:"itemsIndex",
        data: this.data.items[idx],
      })
    } else {
      wx.setStorage({
        key:"itemsIndex",
        data: this.data.items[0]
      })
    }
    wx.navigateTo({
      url: '../menu/menu'
    })
  },

这是通过另外一个页面跳转我的页面的点击事件,用wx.setStorage来存取数据。

wx.getStorage({
      key: 'itemsIndex',
      success: (res) => {
        let storeInfo = this.data.storeInfo;
        storeInfo.name = res.data.name;
        storeInfo.address = res.data.address;
        // console.log(storeInfo);
        this.setData({
          storeInfo
        })
      },
      fail: () => {},
      complete: () => {}
    });

这是在本页面接收数据的方法,并且这个方法要写在onLoad生命周期函数里,这样就可以在页面加载的时候把获取到的数据渲染到页面上。

然后就是本页面含金量最高的部分了

这一部分,应该是所有电商小程序都会用到的。其实说难也不难,说简单也不简单,只要认真看完我下面的讲解,应该就了解要怎么做了。

相信大家看到这个截图之后,内心都有一些自己的想法,那不妨继续看看我的做法,然后与你们自己的想法融合在一起,看看是不是会迸发出新的火花呢!

<!-- 选餐栏 -->
    <view class="menuContent">
        <view class="scrollLeft">
            <scroll-view scroll-y>
                <navigator class="search" url="../" hover-class="none">
                    <image class="searchImage" src="../../images/menuImg/sou-suo.png" />
                    <text class="searchText">搜索</text>
                </navigator>
                <block wx:for="{{scrollLeft}}" wx:key="index">
                    <view class="{{curIndex === index ? 'selected' : 'select'}}" 
                    bindtap="onSelect" 
                    data-index="{{index}}" 
                    data-id="{{item.id}}">
                        <image src="{{item.url}}" 
                        class="selImg" 
                        wx:if="{{curIndex === index}}" />
                        <view class="{{curIndex === index ? 'selectedText' : 'selectText'}}">
                            {{item.name}}
                        </view>
                    </view>
                </block>
            </scroll-view>
        </view>
        <view class="scrollRight">
            <scroll-view scroll-y scroll-into-view="{{toView}}" 
            scroll-with-animation="true" 
            bindscroll="scrollTop" 
            style="height: 1205rpx">
                <block wx:for="{{scrollRight}}" wx:key="index">
                    <view class="food" 
                    wx:for="{{item.detail}}" 
                    wx:key="index" 
                    wx:for-item="food" 
                    id="{{item.id}}">
                        <view class="foodName">{{food.name}}</view>
                        <view class="foodPrice">
                            ¥
                            <view class="foodPriceNum">{{food.price}}</view>
                            起*
                        </view>
                        <image src="{{food.img}}" class="foodPci" />
                        <view class="custom">
                            <view class="customText">去定制</view>
                            <navigator url="../cart/cart"
                             hover-class="none">
                                <view class="customBtn" 
                                bindtap="gotoCart" 
                                data-id="{{item.id}}" 
                                data-index="{{index}}">
                                    <image src="../../images/menuImg/toRight.png" class="customPic" />
                                </view>
                            </navigator>
                        </view>
                        <view class="order">
                            <view class="orderText">大套餐</view>
                            <view class="orderselect" wx:if="{{food.showCombo}}">
                                <view class="reduce" bindtap="OnReduce" data-id="{{item.id}}" data-index="{{index}}">
                                    <image src="../../images/menuImg/jianhao.png" class="orderPic" />
                                </view>
                                <text class="orderTitle">{{food.title}}</text>
                                <view class="add" bindtap="OnAdd" data-id="{{item.id}}" data-index="{{index}}">
                                    <image src="../../images/menuImg/jiahao.png" class="orderPic" />
                                </view>
                            </view>
                            <view class="orderBtn" wx:else bindtap="OnAdd" data-id="{{item.id}}" data-index="{{index}}">
                                <image src="../../images/menuImg/jiahao.png" class="orderPic" />
                            </view>
                        </view>
                    </view>
                </block>
            </scroll-view>
        </view>
    </view>

从页面结构可以看出,这一部分分为左边和右边两部分,然后都通过wx:for循环,将数据循环渲染在页面上,左边和右边也都使用了scroll滚动条,这里有一个坑不知道大家是否踩过,就是使用小程序scroll-view组件时,必须要给这个组件设置固定的高度或者宽度(这采决与你是设置了Y方向滚动还是X方向滚动),如果不设置高度的话,滚动条就会失效,虽然这个坑我已经踩过很多次了,但是每当我遇到时,都还会在踩一遍。

这里由于css太多了,所以就不放上来了展示给大家看了,如果有想看朋友可以去文章最下面的github地址观看。在css里也有一个坑,那就是在选择布局的时候有两种方法,第一种是使用弹性布局,将左边导航栏和右边选餐栏并排一起。第二种是使用display: inline-block;方法,使得左边导航栏和右边选餐栏都变成行内块元素,并排在一起,虽然布局上面没问题,但是当循环数据时,你就会发现右边的数据会倒叙排列,我也没有找到会导致这种方法的原因。所以遇到左右两边需要并排且需要填充数据的时候,推荐使用弹性布局。

接下来就是最最最最难的逻辑部分了,我会给大家分左边和右边来讲解。虽然百度上面也有很多左右联动的逻辑方法,但是百度到的答案不尽人意,所以我就取其精华去其糟粕,写了一下自己的逻辑,接下来我就要给大家细致的讲一下左右联动的效果实现。

我们先来看看点击左边导航栏,然后点击的导航栏变换样式是怎样实现的。

onSelect(e) {
    console.log(e);
    const that = this;
    const curIndex = e.currentTarget.dataset.index;
    const toView = e.currentTarget.dataset.id;
    console.log(toView)
    that.setData({
      curIndex,
      toView
    })
  },

这里通过点击事件,获取到该数据的index并赋值给curIndex,然后通过判断class="{{curIndex === index ? 'selected' : 'select'}}"改变样式。同时点击事件时,也将数据里的id值赋给toView,然后在右边的滚动条里,设置scroll-into-view="{{toView}}",通过这个属性,滚动条就可以自动跳转到对应的toView数据里。这是小程序自定义的方法,可以很方便的做到点击左边,右边自动跳转的操作。但是滚动右边,左边样式也自动切换就不是那么容易的事情了。

.then(res => {
          let heightArr = [];
          const height = 180;
          let heightList = 0
          for(let i = 0; i < res.length; i++) {
            heightList += res[i].detail.length * height;
            heightArr.push(heightList);
          }
          // console.log(heightArr);
          this.setData({
            heightArr
          })
        }) 

在这里,我是在onLoad生命周期函数里,先请求数据,通过.than接收到数据,const height = 180;这是我设置的每一个食物框的固定高度,所以通过这个高度乘以分类里面的每个数据,就可以获得右边滚动条不同分类的高度区间,然后存入heightArr数组。

scrollTop(e) {
    // console.log(e)
    const scrollTop = e.detail.scrollTop;
    if(scrollTop > 100) {
      this.setData({
        hidden: false
      })
    }
    else{
      this.setData({
        hidden: true
      })
    }
    const heightArr = this.data.heightArr;
    for(let i = 0; i < heightArr.length; i++) {
      if(scrollTop > 0 && scrollTop < heightArr[0]) {
        this.setData({
          curIndex: 0
        })
      } else if (scrollTop < heightArr[i] && scrollTop > heightArr[i - 1]) {
        this.setData({
          curIndex: i
        })
      }
    }
  },

右边高度的区间我们已经得到了,然后我们应该怎么利用好它呢?在scroll-view组件里,有一个bindscroll="scrollTop"方法是滚动滚动条时可以触发的事件,这个方法可以获取到滚动的顶部在滚动时距离顶部的距离。那么我们就可以利用这个滚动的距离,然后获取到这个距离在heightArr区间的哪一部分,然后将这个区间的索引值赋值给curIndex。 这样左边的样式就能随右边滚动而改变了。这个方法大家学会了嘛,如果没有看懂,可以在下面评论区问我哟!

OnAdd(e) {
    const id = e.currentTarget.dataset.id;
    const indexSelect = e.currentTarget.dataset.index;
    let totalPrice = this.data.totalPrice;
    let index = id.split('l')[1];
    let scrollRight = this.data.scrollRight;
    const price = scrollRight[index].detail[indexSelect].price;
    scrollRight[index].detail[indexSelect].title++;
    scrollRight[index].detail[indexSelect].showCombo = true;
    totalPrice = totalPrice + price;
    this.setData({
      scrollRight,
      totalPrice
    })
  },
  OnReduce(e) {
    const id = e.currentTarget.dataset.id;
    const indexSelect = e.currentTarget.dataset.index;
    let index = id.split('l')[1];
    let scrollRight = this.data.scrollRight;
    let title = scrollRight[index].detail[indexSelect].title;
    let totalPrice = this.data.totalPrice;
    const price = parseFloat(scrollRight[index].detail[indexSelect].price);
    totalPrice = totalPrice - price;
    if(title > 1) {
      scrollRight[index].detail[indexSelect].title--;
      this.setData({
        scrollRight,
        totalPrice
      })
    }else if(title = 1) {
      scrollRight[index].detail[indexSelect].title--;
      scrollRight[index].detail[indexSelect].showCombo = false;
      this.setData({
        scrollRight,
        totalPrice,
      })
    }
  },

上面是一些简单的加和减的方法,点击+号的时候,触发onAdd事件,获取到当前点击事件的索引值,然后找到数据里面每一项的价格,以及数量,除了将数量+1之外,还需要算出当前所有物品的总价。点击-号的方法一样,我就不再赘述了。

最后就是页面下端的购物车部分了

当选餐时,就会自动跳出购物车按钮,然后点击购物车,就会显示出购物清单列表,在购物清单列表中,也可以增加或者减少食物。

<view class="shoppingList" wx:if="{{showList && totalPrice != 0}}">
        <view class="shadow" bindtap="onList"></view>
        <view class="shoppingBottom">
            <view class="shoppingHeader">
                <view class="hasSelected">
                    <image src="../../images/menuImg/shoppingGray.png" class="image" />
                    <view class="text">已选产品</view>
                </view>
                <view class="empty" bindtap="onEmpty">
                    <image src="../../images/menuImg/lajitong.png" class="image" />
                    <view class="text">清空</view>
                </view>
            </view>
            <scroll-view scroll-y 
                style="max-height: 534rpx">
                <block wx:for="{{scrollRight}}" wx:key="index">
                    <view class="shoppingBody" wx:for="{{item.detail}}" wx:for-item="food" wx:if="{{food.showCombo}}" wx:key="index">
                        <view class="name">{{food.name}}</view>
                        <view class="unitPrice">
                            ¥
                            <view class="unitPriceNum">{{food.price * food.title}}</view>
                        </view>
                        <view class="orderselect addPlace">
                            <view class="reduce" bindtap="OnReduce" data-id="{{item.id}}" data-index="{{index}}">
                                <image src="../../images/menuImg/jianhao.png" class="orderPic" />
                            </view>
                            <text class="orderTitle">{{food.title}}</text>
                            <view class="add" bindtap="OnAdd" data-id="{{item.id}}" data-index="{{index}}">
                                <image src="../../images/menuImg/jiahao.png" class="orderPic" />
                            </view>
                        </view>
                    </view>
                </block>
            </scroll-view>
        </view>
    </view>
    <!-- 选好了 -->
    <view class="shopping" wx:if="{{totalPrice != 0}}">
        <view class="shoppingLeft">
            <view class="shoppingCar" bindtap="onList">
                <image src="../../images/menuImg/shopping.png" class="shoppingImg" />
            </view>
            <view class="shoppingPrice">
                <view class="priceTitle">¥</view>
                <view class="priceNum">{{totalPrice}}</view>
            </view>
        </view>
        <navigator url="../settlement/settlement" class="shoppingRight" bindtap="gotoSettlement" >
            <view class="rightText">选好了</view>
            <image src="../../images/menuImg/yellowRight.png" class="rightImg" />
        </navigator>
    </view>

这是购物清单还有购物车的部分,使用position: fixed;将这部分固定在屏幕的底部,不会随着屏幕滑动而滑动,在结构上面,还设置了一个蒙层,当展示购物清单时显示。

// 是否显示选餐列表
  onList() {
    let showList = this.data.showList;
    showList = !showList;
    this.setData({
      showList
    })
  },
  // 清空事件
  onEmpty() {
    const scrollRight = this.data.scrollRight;
    for(let i = 0; i < scrollRight.length; i++) {
      for(let j = 0; j < scrollRight[i].detail.length; j++) {
        scrollRight[i].detail[j].title = 0;
        scrollRight[i].detail[j].showCombo = false;
      }
    }
    this.setData({
      scrollRight,
      totalPrice: 0,
      showList: false
    })
  },
  // 跳转到cart页面
  gotoCart(e) {
    // console.log(e)
    const id = e.currentTarget.dataset.id;
    const indexSelect = e.currentTarget.dataset.index;
    let index = id.split('l')[1];
    let scrollRight = this.data.scrollRight;
    const zhushi = scrollRight[index].detail[indexSelect];
    console.log(zhushi);
    wx.setStorage({
      key: "cartFood",
      data: zhushi
    })
  },

这些方法都是基本方法,还是很简单的,大家看一下应该就知道做什么的了,也不再一一介绍了。

啊啊啊啊啊啊啊啊啊啊,好累,码了这么多字,感觉写文章比写小程序还累!但是我不能停下来,因为还有重点没有讲!

接下来就是这篇文章的重点部分了,小伙伴们快竖起耳朵听啊!

爬虫爬取数据

相信大家在写小项目的时候,最头疼的就是写假数据了,每次编写假数据,自己看的都头皮发麻。所以我给大家带来一个简单的爬虫,不仅可以轻轻松松的获取到数据,而且显得既高端又专业!

我把爬虫写在了云函数里,这样可以直接在运行云函数的时候,就把爬虫爬取到的数据直接存储到云数据库。在写爬虫之前,首先需要将运行环境初始化成node运行环境,然后下载基本的依赖,以便后面可以在网页上获取数据。因为我这里要获取到的数据在不同的页面里,所以我先将网页全部定义好,方便直接引用。同时我也创建了不同的空数组,为了将从不同网页中获取到的不同数据存入不同的数组里。这些准备工作都做完了,下面来看看代码吧。

const cloud = require('wx-server-sdk');
const request = require('request');
const cheerio = require('cheerio');
const breakfast = 'http://www.5ikfc.com/mdl/menu/breakfast/';  //早餐
const chaozhitaocan = 'http://www.5ikfc.com/mdl/menu/chaozhitaocan/';  //超值套餐
const happymeals = 'http://www.5ikfc.com/mdl/menu/happymeals/';  //快乐套餐
const sides = 'http://www.5ikfc.com/mdl/menu/sides/';  //配餐
const drink = 'http://www.5ikfc.com/mdl/menu/drink/';  //饮料
const dessert = 'http://www.5ikfc.com/mdl/menu/dessert/';  //甜品
const mccafe = 'http://www.5ikfc.com/mdl/menu/mccafe/';  //麦咖啡
let breakfastList = [];
let chaozhitaocanList = [];
let happymealsList = [];
let sidestList = [];
let drinkList = [];
let dessertList = [];
let mccafeList = [];

// 初始化 cloud
cloud.init()

const db = cloud.database();

function maidanglaoSpider(http, list) {
    return new Promise((resolve, reject) => {
        request(http,
        (err, res) => {
            if(err) {
                reject('net error');
            }
            if(!err) {
                const body = res.body;
                const $ = cheerio.load(body, {
                decodeEntities: false
                })
                $('.lside.fr.bdgrey.main_wrap .fx li')
                .each(function() {
                    const img = $('a img', this).attr('src');
                    const name = $('a', this).text().trim();
                    const price = $('b', this).text().trim();
                    list.push({
                        name,
                        img,
                        price
                    })
                    console.log({
                        name,
                        img,
                        price
                    })
                })
                resolve(list);
            }
        })
    })
}
maidanglaoSpider(breakfast,breakfastList)
.then(res => {
    console.log(res);
})

首先往爬虫函数里传http和list两个参数,因为我需要将不同网页的数据存入不同的list里面。然后函数return一个Promise函数,然后在promise函数里发起请求,如果请求没有报错的话,就const body = res.body获取网页的html的body结构,然后通过('.lside.fr.bdgrey.main_wrap .fx li')找到我们在网页中需要的节点。通过const img =('a img', this).attr('src');获取我们需要的图片的src;通过const name = ('a', this).text().trim();获取到我们需要的名字;通过const price =('b', this).text().trim();获取到需要的价格。最后将这三个数据以对象的形式push进数组,然后resolve出来。到这里我们的爬虫函数就写好啦,然后下面就需要把数据传入云数据库了。

exports.main = async (event, context) => {
        const breakfastData = await maidanglaoSpider(breakfast, breakfastList);
        const chaozhitaocanData = await maidanglaoSpider(chaozhitaocan, chaozhitaocanList);
        const happymealsData = await maidanglaoSpider(happymeals, happymealsList);
        const sidesData = await maidanglaoSpider(sides, sidestList);
        const drinkData = await maidanglaoSpider(drink, drinkList);
        const dessertData = await maidanglaoSpider(dessert, dessertList);
        const mccafeData = await maidanglaoSpider(mccafe, mccafeList);
        let arrData = [breakfastData,chaozhitaocanData,happymealsData,sidesData,drinkData,dessertData,mccafeData]
        
        for(let i = 0; i < arrData.length; i++) {
            await db.collection('food').add({
                data: {
                    id: i,
                    detail: arrData[i]
                }
            })
        }
}

我首先将不同的数据命名好,然后将他们放进arrData数组里,然后通过遍历这个数组,把每一项数据都存入云函数里。

云数据库内容如下

当我同一个小组的大佬看到我的云数据库以后,对我进行了夸赞:“您真是将数据库运用到了极致。”当然了,这并不是夸赞,而是无情的嘲讽。我在存数据的时候,将所有数据存在了一个集合中,并且在集合中将数据划分开来(这是极度错误的做法,希望大家不要效仿我),由于这是我第一次使用云数据库存数据,所以犯这种错误也能体谅。

正确做法是:将每一个种类的数据,存放在一个集合中,不要吝啬数据库的使用。

获取数据

上面我们已经把爬虫的数据存进云函数了,然后就到了获取数据的时候了。

wx.cloud.callFunction({
      name: 'foodData',
      success: (res) => {
        // console.log(res);
        db.collection('breakfast')
        .get()
        .then(res => {
          let food = {};
          food.id =  `l${res.data[0].id}`
          food.detail = res.data[0].detail.slice(0,5);
          food.title = 0;
          let scrollRight = this.data.scrollRight;
          scrollRight.push(food);
          this.setData({
            scrollRight
          })
          return res
        })
        .then(res => {
          let food = {};
          food.id =  `l${res.data[1].id}`
          food.detail = res.data[1].detail.slice(0,5);
          food.title = 0;
          let scrollRight = this.data.scrollRight;
          scrollRight.push(food);
          this.setData({
            scrollRight
          })
          return res
        })
        .then(res => {
          let food = {};
          food.id =  `l${res.data[2].id}`
          food.detail = res.data[2].detail.slice(0,5);
          food.title = 0;
          let scrollRight = this.data.scrollRight;
          scrollRight.push(food);
          this.setData({
            scrollRight
          })
          return res
        })
        .then(res => {
          let food = {};
          food.id =  `l${res.data[3].id}`
          food.detail = res.data[3].detail.slice(0,5);
          food.title = 0;
          let scrollRight = this.data.scrollRight;
          scrollRight.push(food);
          this.setData({
            scrollRight
          })
          return res
        })
        .then(res => {
          let food = {};
          food.id =  `l${res.data[4].id}`
          food.detail = res.data[4].detail.slice(0,5);
          food.title = 0;
          let scrollRight = this.data.scrollRight;
          scrollRight.push(food);
          this.setData({
            scrollRight
          })
          return res
        })
        .then(res => {
          let food = {};
          food.id =  `l${res.data[5].id}`
          food.detail = res.data[5].detail.slice(0,5);
          food.title = 0;
          let scrollRight = this.data.scrollRight;
          scrollRight.push(food);
          this.setData({
            scrollRight
          })
          return res
        })
        .then(res => {
          let food = {};
          food.id =  `l${res.data[6].id}`
          food.detail = res.data[6].detail.slice(0,5);
          food.title = 0;
          let scrollRight = this.data.scrollRight;
          scrollRight.push(food);
          console.log(food);
          this.setData({
            scrollRight
          })
          return res
        })

本来我想的是利用循环,把数据遍历出来,然后通过循环存进定义的空数组里。但是我怎么也存不进去,实在找不到原因,我就把数据的每一项都单独拎出来然后存进去。虽然代码很不美观,但是总算把数据存进去了。这个函数要写在onLoad生命周期函数里,这样可以在页面加载的时候就把数据获取到,然后渲染到页面上。

至此,我的个人页面就完成了,小伙伴们也将他们的页面提交到了github上面,本以为工作就结束了,可以高高兴兴的玩耍了。但是转头一想,页面跳转的工作还没人做呢,哎,谁让我是小组长呢,只能由我这个“老父亲”来做收尾工作了。

收尾工作

其实收尾工作很简单,就是改一下路由跳转,并且传送一下对应的数据就行。

传送和接收数据代码如下:

wx.setStorage({
        key:"itemsIndex",
        data: this.data.items[idx],
    })
wx.getStorage({
      key: 'itemsIndex',
      success: (res) => {
        let storeInfo = this.data.storeInfo;
        storeInfo.name = res.data.name;
        storeInfo.address = res.data.address;
        // console.log(storeInfo);
        this.setData({
          storeInfo
        })
      },
      fail: () => {},
      complete: () => {}
    });

在跳转页面时,利用wx.setStorage将数据放入缓存区,然后在需要数据的页面,利用wx.getStorage获取缓存区的数据。

好啦,工作算是结束了,给大家来看看我们的最终成果把!

嘿嘿,总体来说,还算过得去吧

一些总结

小程序写完了,总得有一些工作总结对吧,我觉得通过这次几个小伙伴通力合作,我感慨还是蛮多的,给大家总结一下几点吧!

  • 第一!最重要的就是!心平气和。几个小伙伴合作写项目,难免在一些观点上面有分歧,但是大家一定要心平气和的商讨,不能各执己见。虽然我们团队在写项目的时候也有几句争吵,但是总体来说还算平和。
  • 第二!一定要注意代码的质量,以前一直是一个人写代码,没有体会到代码质量的重要性,但是通过这次合作,我发现代码一定要写的简单易懂,也要多写注释,这样方便别人修改你的代码,同时也方便自己阅读。
  • 第三!一定要坚持,有些事情看似很难,但是只要坚持下来,你会发现那些困难,再一点点土崩瓦解,到最后会被你完全击溃。
  • 第四!不懂就问,不管是老师,同学,还是百度,不懂就要去问,不能把问题放在那里不解决,只要多问多思考,就会一点点有思路了。

以上几点就是这次小项目完成的总结啦,同时也是这篇文章的收尾了,这篇文章是我第一次写文章,所以我知道可能很差,所以大家有什么建议的话,一定要给我留言,方便我改进,同时如果大家对这个项目有什么不懂的,也可以在留言区问,我会细心解答的!

这是这个项目的github地址:github.com/Yeqing98/Ma… (有需要的小伙伴可以拿去参考一下噢!)