内容简介:hello大家好,这是我的第一篇掘金文章,每天都在掘金上面看各位大佬的文章,终于鼓足勇气决定写一篇属于自己的文章了。今天呢,就给大家带来一篇微信小程序(麦当劳点餐)+爬虫的详解吧。大佬们可以忽略我这个小辣鸡,但是如果你也是前端小白的话,可以认真看看哟,说不定对你有帮助呢。这个小程序是为最近参加的一个小活动而制作的(为期两天,3-4人组队,完成一个小型项目)。说实话,两天怎么可能完成一个小程序呢?在前两天,我们大致完成了小程序基本结构,然后由我完成收尾工作,前前后后历时四天。大家可以看到,这个小程序有四个页面
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结构,然后通过 ('a img', this).attr('src');获取我们需要的图片的src;通过const name = ('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… (有需要的小伙伴可以拿去参考一下噢!)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Python3网络爬虫(十一):爬虫黑科技之让你的爬虫程序更像人类用户的行为(代理IP池等)
- 50行代码实现一个并发的 Python 爬虫程序
- 博彩骗局、违法爬虫:程序员还要警惕哪些“深坑”?
- 王者程序员整理的Python网络爬虫和web的系统学习路线图
- 爬虫需谨慎,那些你不知道的爬虫与反爬虫套路!
- 反爬虫之字体反爬虫
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
自制编程语言 基于C语言
郑钢 / 人民邮电出版社 / 2018-9-1 / CNY 89.00
本书是一本专门介绍自制编程语言的图书,书中深入浅出地讲述了如何开发一门编程语言,以及运行这门编程语言的虚拟机。本书主要内容包括:脚本语言的功能、词法分析器、类、对象、原生方法、自上而下算符优先、语法分析、语义分析、虚拟机、内建类、垃圾回收、命令行及调试等技术。 本书适合程序员阅读,也适合对编程语言原理感兴趣的计算机从业人员学习。一起来看看 《自制编程语言 基于C语言》 这本书的介绍吧!