欢迎点击「算法与编程之美」↑关注我们!
本文首发于微信公众号:"算法与编程之美",欢迎关注,及时了解更多此系列文章。前言
前言
前一篇博客为大家简单的讲解了一下关于一个简单的电商小程序的首页和分类页面的制作。这篇博客呢,继续为大家讲解后面搜索页、详情页、购物车页面的制作。
搜索页
1.事实上在大多数的电商平台里,首页显示的搜索框不是真正的搜索框,而是你点击之后,会进入一个搜索页面(由另外一个页面上完成的)。
2.在搜索页面里面默认展示的搜索热词可以使用van-tag来显示,判断item.highlight属性,为true就高亮显示。
3.使用van-search组件搭建搜索, bind :change在函数里得到输入的值,set给value,onSearch事件里面带上value请求搜索接口http://www.xiongmaoyouxuan.com/api/search?word” this.data.value
希望热词隐藏,搜索结果显示,使用van-card显示商品列表,使用wordsShow控制热词的显示 wx:if = “{{wordsShow}}”。
4.点击热词,bind:tap= “onHotWordTap”,在时间里面获取热词文字,set给value,调用onSearch方法就可以完成搜索。
扩展:
1.排序:点击按价格排序,请求同一个接口,参数sort=1,那么这个时候接口返回的数据就是按照价格排好序的数据,再set回给list,那么list就是按照价格渲染了,sort=2就是按照销量排序
2.上拉加载:start默认为0, 每一次触底start =40,继续请求下40条数据,请求下来以后把这40条添加到list里面,包括loading图标
详细代码如下:
1.Js部分:
/** * 页面的初始数据 */ data: { value: "", hotWords : [], // 搜索热词 list : [], // 搜索商品结果列表 wordsShow : true }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { var _this = this; // 请求搜索热词的接口 wx.request({ url: 'http://www.xiongmaoyouxuan.com/api/search/home', method : "GET", success : function (res) { console.log(res.data.data.hotWords); _this.setData({ hotWords: res.data.data.hotWords }); } }) }, onSearch : function () { var _this = this; // 带上value值请求搜索 wx.request({ url: 'http://www.xiongmaoyouxuan.com/api/search?word=' this.data.value, method : "GET", success : function (res) { console.log(res.data.data.list); _this.setData({ list: res.data.data.list, wordsShow : false }) } }) }, onFocus : function () { // 让热词显示,让搜索结果隐藏 this.setData({ wordsShow : true }); }, onChange : function (evt) { console.log(evt.detail); // 把输入框手动输入的值设置给value数据 this.setData({ value : evt.detail }); }, onHotWordTap : function (evt) { // 得到点击热词的文字内容 // 带着文字内容请求搜索 console.log(evt) console.log(evt.currentTarget.dataset.word); this.setData({ value: evt.currentTarget.dataset.word }); // 调用onSearch方法 this.onSearch(); } |
---|
2.json部分:
{ "usingComponents": { "van-search": "/dist/search/index", "van-tag": "/dist/tag/index", "van-card": "/dist/card/index" } } |
---|
3.wxml部分
<viewclass='page'> <view> <van-search value="{{ value }}" placeholder="请输入搜索关键词" show-action bind:change="onChange" bind:search="onSearch" bind:focus="onFocus" /> </view> <viewclass='hot-container'wx:if="{{ wordsShow }}"> <viewwx:for="{{hotWords}}"class='hot-tag'> <van-tag bindtap="onHotWordTap" data-word="{{item.word}}" plain type="{{item.highlight ? 'danger' : 'primary'}}" size="large" > {{item.word}} </van-tag> </view> </view> <viewwx:else> <blockwx:for="{{list}}"> <van-card tag="{{item.couponValue}}" price="{{item.price}}" origin-price="{{item.originPrice}}" title="{{item.title}}" thumb="{{ item.image }}" > </van-card> </block> </view> </view> |
---|
详情页
1.在商品列表绑定tap事件,并且使用data-id=”{{item.id}}”将这条商品的id传递过去,在事件函数里接受参数evt,evt.currentTarget.dataset.id可以取到当前商品的id,然后wx.navigateTo跳转到详情页的时候携带id过去
2.在详情页的onload里,options.id可以接受到跳转过来的时候携带的id值,然后根据此id值请求详情页接口,得到数据,渲染详情页
详细代码如下:
1.Js部分:
data: { detail : {}, // 当前商品的详细信息 swiperWidth : wx.getSystemInfoSync().screenWidth, cartNum : 0// 购物车商品数量 }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { // 获取购物车数量 this.setData({ cartNum: utils.calcCartNum() }) var _this = this; // 取到跳转过来的时候传递的id值 var id = options.id; // 携带id去接口请求当前商品详情数据 wx.request({ url: 'http://www.xiongmaoyouxuan.com/api/detail?id=' id, method: "GET", success : function (res) { console.log(res); _this.setData({ detail : res.data.data.detail }) } }) }, onAddToCart : function (evt) { let _this = this; // 购物车存储当前商品的信息 var obj = { id: this.data.detail.id, title: this.data.detail.title, image: this.data.detail.photos[0].url, price : this.data.detail.price, checked : false, num : 1 } // 判断这条商品在购物车里是否已经存在 // 把本地存储的cart取出来 wx.getStorage({ key: 'cart', success: function(res) { console.log(res); // 说明已经存储过购物车了 // 在之前的基础之上再把当前这条商品加进去 // 如果这条商品再购物车里已经存在,那么就num // 如果不存在,那么就把这条商品的obj push到数组里 // 数组操作完成以后,重新存进storage var isExist = false; var cart = res.data; for(var i = 0 ; i < cart.length; i ){ if(cart[i].id === obj.id){ // 说明购物车里已经存在这条商品 cart[i].num ; isExist = true; break; } } if(!isExist) { // 说明购物车里不存在当前商品 cart.push(obj); } // 将cart重新存进storage进行覆盖 wx.setStorage({ key: 'cart', data: cart }) Toast('添加购物车成功'); _this.setData({ cartNum : utils.calcCartNum() }) }, fail: function (err) { // 代表购物车为空 // 存储当前这一条商品 // 存一个数组,目的是方便下一次存新的数据往里面去添加 wx.setStorage({ key: 'cart', data: [ obj ] }) } }) } }) |
---|
2.json部分:
{ "usingComponents": { "van-goods-action": "/dist/goods-action/index", "van-goods-action-icon": "/dist/goods-action-icon/index", "van-goods-action-button": "/dist/goods-action-button/index", "van-toast": "/dist/toast/index" } } |
---|
3.Wxnl部分:
<viewclass=’page’> <viewclass=’swiper’> <swiper indicator-dots=”{{true}}” autoplay=”{{true}}” circular=”{{true}}” interval=”{{3000}}” duration=”{{400}}” style=”width:{{swiperWidth}}px; height:{{swiperWidth}}px” > <blockwx:for=”{{detail.photos}}”> <swiper-item> <imagesrc=”{{item.url}}”class=”slide-image”/> </swiper-item> </block> </swiper> </view> <view> <text>{{detail.title}}</text> <text>¥{{detail.price}}</text> <view> <imageclass=’shopImg’src=’{{detail.shop.picUrl}}’></image> <text>{{detail.shop.title}}</text> <text>最近上新{{detail.shop.updateTime}}</text> </view> </view> <viewclass=’detail-list’> <blockwx:for=”{{detail.descContentList}}”> <imagemode=’widthFix’style=’width:{{swiperWidth}}px;’src=’{{item.photo.url}}’></image> </block> </view> <van-goods-action> <van-goods-action-iconicon=”chat-o”text=”客服”/> <van-goods-action-icon icon=”cart-o” text=”购物车” info=”{{cartNum}}” url=”/pages/cart/cart” link-type=”switchTab” /> <van-goods-action-iconicon=”shop-o”text=”店铺”/> <van-goods-action-buttontext=”加入购物车”type=”warning”bind:click=”onAddToCart”/> <van-goods-action-buttontext=”立即购买”/> </van-goods-action> <van-toastid=”van-toast”/> </view> |
---|
购物车
1.存购物车:通过wx.setStorage存储,wx.getStorage取,如果storage里没有数据,那就把当前这条商品放到空数组里存进去,如果storage里已经有数据,那就先把数据取出来,判断已存的数据里是否存在当前商品(通过id判断),如果已经存在,则num ,如果不存在,则将此商品push到数组中并重新存一下以达到覆盖
2.取购物车:从storage里把数据取出来,列表渲染到页面上。购物车编辑:选框修改的时候判断选框是否选中来决定总价的加减;步进器来设
详细代码:
1.js部分:
data: { cart : [], // 存储购物车所有信息 totalPrice : 0, // 提交商品的总价 allchecked: false, // 全选按钮的状态 checkedNum: 0, // 被勾选的商品数量 cartNum : 0, // 购物车商品总数量 scrollHeight : wx.getSystemInfoSync().windowHeight - 110 }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { var _this = this; wx.getStorage({ key: 'cart', success: function(res) { console.log(res.data); _this.setData({ cart : res.data }) } }) }, /** * 生命周期函数--监听页面显示 */ onShow: function () { // 计算商品总数量 this.setData({ cartNum: utils.calcCartNum() }) }, onChange: function (evt) { var _this = this; // 用户编辑商品数量 console.log(evt); // 从storage里把数据取出来,然后找到正在编辑的额这一条,再把数量变成evt.detail wx.getStorage({ key: 'cart', success: function(res) { let cart = res.data; for(var i = 0; i < cart.length; i ){ if(cart[i].id === evt.currentTarget.dataset.id){ cart[i].num = evt.detail; } } wx.setStorage({ key: 'cart', data: cart }) // 重新计算购物车总数 _this.setData({ cartNum : utils.calcCartNum() }) } }) }, // 选择某个商品 onCheckChange : function (evt) { console.log(evt); // 得到当前商品的索引 let index = evt.currentTarget.dataset.index; // 将当前商品的checked属性设置为change之后的checked属性 let cart = this.data.cart; cart[index].checked = evt.detail; let totalPrice = this.data.totalPrice/100; // 判断是取消还是选中 if(evt.detail) { // 选中 totalPrice = cart[index].price * cart[index].num; this.setData({ checkedNum : this.data.checkedNum }) }else{ // 取消 totalPrice -= cart[index].price * cart[index].num; this.setData({ checkedNum: --this.data.checkedNum }) } // 选中数量跟cart.length相等的话那么全选 console.log(totalPrice); this.setData({ cart : cart, totalPrice : totalPrice*100, allchecked: this.data.checkedNum === cart.length }) }, // 全选按钮的状态改变 onAllChange : function (evt) { var cart = this.data.cart; var total = 0; // 所有商品的选中状态跟着全选按钮一起改变 for(var i = 0; i < cart.length; i ){ cart[i].checked = evt.detail; total = cart[i].price * cart[i].num; } this.setData({ allchecked: evt.detail, cart : cart, totalPrice: evt.detail ? total*100 : 0 }) }, // 长按删除某条商品 onDelete : function (evt) { var id = evt.currentTarget.dataset.id; console.log(id); Dialog.confirm({ message: '你确定要删除吗?' }).then(() => { // 从cart找到当前商品并且删除,再把删除之后的结果存storage let cart = this.data.cart; for (var i = 0; i < cart.length; i ) { if (cart[i].id === id) { // 从下标为i的位置删除一条数据 cart.splice(i, 1); break; } } wx.setStorage({ key: 'cart', data: cart }) this.setData({ cart: cart, cartNum: utils.calcCartNum() }); }).catch(() => { // on cancel }); }, // 提交结算 onSubmit : function () { // 把要结算的商品存到storage里,跳转到结算页 let cart = this.data.cart; // map filter some every reduce var checkedCart = []; for(var i = 0; i < cart.length; i ){ cart[i].checked && checkedCart.push(cart[i]); } wx.setStorage({ key: 'pay', data: checkedCart }) wx.navigateTo({ url: '/pages/pay/pay' }) } }) |
---|
2.json部分:
{ "usingComponents": { "van-checkbox": "/dist/checkbox/index", "van-stepper": "/dist/stepper/index", "van-submit-bar": "/dist/submit-bar/index", "van-dialog": "/dist/dialog/index" } } |
---|
3.wxml部分:
<viewclass='page'> <viewclass='cart-head'> <textclass='head-title'>购物车({{cartNum}})</text> </view> <scroll-view class='cart-list' style='height:{{scrollHeight}}px'scroll-y> <viewwx:for="{{cart}}"class='cart-item'wx:for-index="idx"bindlongtap='onDelete'data-id="{{item.id}}"> <viewclass='cart-radio'> <van-checkbox checked-color="#fef739" value="{{item.checked}}" bind:change="onCheckChange" data-index="{{idx}}" > </van-checkbox> </view> <viewclass='cart-image'> <imagesrc='{{item.image}}'></image> </view> <viewclass='cart-main'> <textclass='cart-title'>{{item.title}}</text> <van-stepper value="{{ item.num }}" bind:change="onChange" data-id="{{item.id}}" /> <textclass='cart-price'>¥{{item.price}}</text> </view> </view> </scroll-view> <van-submit-bar price="{{ totalPrice }}" button-text="结算" bind:submit="onSubmit" > <van-tagtype="primary"> <van-checkbox value="{{ allchecked }}" bind:change="onAllChange" checked-color="#fef739" > 全选 </van-checkbox> </van-tag> </van-submit-bar> <van-dialogid="van-dialog"/> </view> |
---|
结语
关于这个小程序的简单学习就告一段落了,可能觉得并没有学到很多,其实这个主要的目的是带领大家去接触小程序,去走进它,至于最后愿不愿意深入学习,不同的人就会有自己不同的想法了。
更多精彩文章:
算法|从阶乘计算看递归算法
算法|字符串匹配(查找)-KMP算法
JavaScript|脚本岂能随意放置
开发|优秀的Java工程师的“对象”一定不错
谈一谈|2019蓝桥杯回顾与分享
where2go 团队
微信号:算法与编程之美
温馨提示:点击页面右下角“写留言”发表评论,期待您的参与!期待您的转发!