微信小程序实战(仿小米商城)

├── assets 用到的一些图标文件

├── lib

├── weui.wxss 引用了weui

├── modules

├── showDetail.js 跳转展示商品详情的公共js文件

├── showcDetail.js

├── pages 项目的各个页面

├── index 商城首页

├── categories 商品分类页

├── discovery 发现页

├── channel 商品频道目录

├── phone 手机频道

├── tv 电视频道

├── computer 电脑频道

├── cart 购物车

├── mine 个人信息页

├── goods 商品详情页

├── selectGoods 商品属性选择页

├── search 商品搜索页

├── addr 收货地址页

├── template 使用到的模版文件

├── slide 轮播图模版

├── goods_list 商品展示模版

├── cover 商品展示模版

├── util 使用到的工具类

├── mock.js 项目中使用到的一些数据

├── app.js 项目逻辑

├── app.wxss 项目公共样式表

└── app.json 项目公共设置

功能的展示与实现


一、商城首页

页面结构分析:

  • 顶部搜索条

这里看上去是一个搜索框,但其实,它要实现的仅仅是个页面跳转功能,只要把它的disabled设置为true就可以了,另外要想让它placeholder占位符居中显示的话,微信小程序提供了一个placeholder-class的属性,通过它可以改变placeholder的样式。

  • 轮播图区域

这里微信小程序给我们提供了swiper组件,直接用就可以了。但是轮播图在各个页面都可能存在,只是其中所显示的图片不一样而已,所以使用组件化思想,把它写成一个模版,哪里要使用,就引入这个模版即可。

使用时,这样引入

  • 商城导航区、活动区

这里只是个简单的布局,就不赘述了。但是需要注意的是在微信小程序里,强烈推荐使用弹性布局

  • 首页商品展示区

这里的商品都是分块展示,很有规律,因此整个商品展示都可以直接用wx:for遍历出来。

wxml:

{{product.header}}

{{product.description}}

{{product.meta}}

{{product.discount}}

这里有个细节,每个版块里的商品会分成“新品”、“立减”(即有折扣)、“无折扣”三种,着该怎么去做呢?这里我用了一个巧妙的方法:给每个商品的class里绑定布尔值is_newon_sale通过三元运算符判断是否给该商品挂载一个类名,再使用伪元素给该商品打上“新品”或“立减”的标签如下:

wxml:

wxss

.goods-img.new:before{ /新品标签样式/

position: absolute;

left: 0;

top: 0;

width: 100rpx;

height: 40rpx;

line-height: 40rpx;

content: “新品”;

color: #fff;

font-size: 9pt;

text-align: center;

background: #8CC64A;

}

.goods-img.on-sale:before{ /立减标签样式/

position: absolute;

left: 0;

top: 0;

width: 100rpx;

height: 40rpx;

line-height: 40rpx;

content: “立减”;

font-size: 9pt;

color: #fff;

text-align: center;

background: #ec6055;

}

逻辑分析:

首页只是些商品,所以逻辑层只要根据每个商品的id来跳到对应商品的详情页即可,很显然这个方法在多个页面都要使用的,所以使用模块化思想,创建一个modules文件夹,把方法写在单独的js文件里,并向外输出

const showDetail=(e)=>{

const id=e.currentTarget.dataset.pid; //获取每个商品的id

wx.navigateTo({

url: /pages/goods/show?id=${id}

})

};

export default showDetail;

哪里要使用,就用import引入

import showDetail from “…/…/modules/showDetail”;

二、商品分类页

页面结构分析:

商品分类页分为左侧的商品分类菜单和右边的商品分类展示区,

用两个scroll-view就可以了,左右两边都设置scroll-y让它们垂直方向滚动,此外,scroll-view还有一个scroll-into-view属性能让我们实现类似a标签的锚点功能,scroll-into-view的值是某个子元素的id,但是此处有一个小坑这个id不能以数字开头

当时查了一下文档就开做了,于是乎给左侧菜单取了些数字id,现在想起来当时我太自以为然了 ,此外如果内容太多,是会产生滚动条的,如图:

这样看起来也太丑了。。

**解决办法:给全局样式加入下面的样式

//隐藏滚动条

::-webkit-scrollbar{

height: 0;

width: 0;

真题解析、进阶学习笔记、最新讲解视频、实战项目源码、学习路线大纲
详情关注公中号【编程进阶路】

color: transparent;

}

嗯,beautiful !!

商品分类功能

逻辑分析:给页面注册个curIndex(当前选中菜单的下标),如果当前下标和选中的菜单下标相同,则处于激活状态

部分代码:

wxml:

<view class=“cate-nav-list” wx:for=“{{cate_nav_list}}” wx:key=“{{item.id}}” data-id=“{{item.id}}” data-index=“{{index}}”

bindtap=“switchCategory”>

{{item.name}}

{{item.cate_name}}

{{cateList.item_name}}

js:

const app=getApp();

Page({

/**

  • 页面的初始数据

*/

data: {

cate_nav_list:[

{name:“新品”,id:“new”},

{name:“手机”,id:“phone”},

{name:“电视”,id:“tv”},

{name:“电脑”,id:“laptop”},

{name:“家电”,id:“appliance”},

{name:“路由”,id:“router”},

{name:“智能”,id:“smart”},

{name:“儿童”,id:“kids”},

{name:“灯具”,id:“lignts”},

{name:“电源”,id:“adapter”},

{name:“耳机”,id:“headset”},

{name:“音箱”,id:“voicebox”},

{name:“生活”,id:“life”},

{name:“服务”,id:“service”},

{name:“米粉卡”,id:“card”}

],

curIndex:0, //初始化当前下标为0

toView:“new”, //默认显示“新品展示”

detail:[]

},

switchCategory(e){

const curIndex=e.currentTarget.dataset.index?e.currentTarget.dataset.index:0; //获取每个菜单的id

//更新数据

this.setData({

toView:e.currentTarget.dataset.id,

curIndex

});

},

onLoad: function (options) {

const detail=app.globalData.category; //获取分类展示数据

this.setData({

detail

});

}

})

三、发现页

页面结构分析:

里面展示了一些商品宣传视频(当时还是不太想切太多的页面😂)这里用弹性布局+video组件就搞定了。这里是文档

四、商品详情页

页面结构分析:

商品详情顶部由一个swiper组成,中间部分由一些cells组成(weui)点击这里快速查看

底部是商品的概述及参数配置两部分组成,这个还是比较简单的, 给两个元素分别绑定一个布尔值来控制谁显示谁隐藏。

当然,要使用weui必须引入它的样式文件,我们在app.wxss里引入,然后全局都可以使用了

@import “./lib/weui.wxss”;

嗯,weui的官网和github地址自然少不了。weui官网 、weui github官方文档,在github上阅读代码是一个非常有效的学习方式,但是文件夹嵌套太深找个文件也不容易,这里奉上github阅读神器

使用到的weui:

请容许我贴一段weui抄来的结构

{{goods.header}}

{{goods.description}}

{{goods.meta}}

商品详情页的显示

逻辑分析:

每个商品通过id来跳转到相应的详情页,但是这个id会在哪里呢因为先这个详情页是通过一个个商品来打开的,所以在商品详情页加载时,可以在 onLoad 中获取打开当前页面所调用的 query 参数(是条json数据),因为在showDetail里只用了id来跳转,所以options只有id属性

onLoad: function (options) {

console.log(options); //{id:“4”}

const id=options.id; //获取options里的id

const goods=app.globalData.goodsDetail.filter(item=>{

return item.id==id; //通过id来筛选显示对应的商品

});

this.setData({

goods:goods[0] //因为id是唯一的,所以上面筛选出来的数组只有一条数据,这条数据就是要显示的商品数据

});

}

商品图片预览实现

微信小程序为我们提供了wx.previewImage()方法来实现图片的预览,实现方法如下:

previewImage(e){

const index=e.currentTarget.dataset.index; //获取swiper里的图片的下标

const slide=this.data.goods.goods_slides; //获取商品轮播图

const imgList=[]; //定义一个数组来存放轮播图的url

slide.map(item=>{

imgList.push(item.slide_url); //用js的map方法把图片的url地址取出来放到数组里

});

wx.previewImage({

current: imgList[index], // 当前显示图片的链接,不填则默认为 urls 的第一张

urls: imgList

})

}

五、商品属性选择

页面结构:整个商品属性页的结构是由一些cells组成,所以用weui最合适(插一段:原生的radio真的是很丑,不过weui对它做了改进)

一开始想有weui就简单多了,直接用form表单的bindsubmit处理就可以了,奈何在weui里使用bindsubmit,取不到radio的值,折腾了很久,还是取不到,但是换成原生的radio竟可以取到!!

这个不行,那就换一种吧,用weui radiogroup里的bindchange事件吧,虽然繁琐了些,但是还是能解决问题的。。

话不多说,看代码(感觉写了一些很累赘的代码。。)

selectVersion(e) {

const version = e.detail.value;

const memory = version.split(“,”)[0];

const price = version.split(“,”)[1];

wx.setStorageSync(‘memory’, memory);

wx.setStorageSync(‘price’, price);

this.setData({

memory,

price

});

},

selectColor(e) {

let color = e.detail.value;

let cover_img=this.data.goods_attrSelect[0].goods_slides[0].slide_url;

wx.setStorageSync(‘color’, color);

wx.setStorageSync(‘cover’, cover_img);

this.setData({

color,

cover_img

});

},

colorHasSelected(e) {

const curcIndex = e.currentTarget.dataset.index ? e.currentTarget.dataset.index : 0;

console.log(curcIndex);

this.setData({

curcIndex

});

},

versionHasSelected(e) {

const curvIndex = e.currentTarget.dataset.index ? e.currentTarget.dataset.index : 0;

console.log(curvIndex);

this.setData({

curvIndex

});

}

对应商品的属性页的跳转

逻辑分析:在商品详情页中,通过当前商品的id跳转

toSelect(e){

const id=e.currentTarget.dataset.id;

wx.navigateTo({

url:../selectGoods/selectGoods?id=${id}

});

}

在商品的属性选择页里,同样是通过id筛选显示不同商品的属性选择信息

onLoad: function (options) {

const id = options.id;

console.log(id);

const goods_attrSelect = app.globalData.goodsDetail.filter(item => {

return item.id == id;

});

}

商品属性的联动选择

既然是商品,没有属性选择怎么行呢?兴致一来二话不说就是写。但是这里有一个难点:用户的选择多样性,难道你会把所有用户可能做出的选择都列出来吗?天哪,商品这么多,这是要累死我吗?no,no,no,这种方法不可取。哪还有什么解决办法呢?当时一想到的就是用数据缓存,嗯,这种方法可行,但是用缓存存取用户选择的值的话,这里有一个很大的问题:微信小程序里的数据缓存将data存储在本地缓存中指定的key中,会覆盖掉原来该key对应的内容,无论是wx.setStorage(异步接口)还是wx.setStorageSync(同步接口),这样的话,无论用户选择了多少个商品,只要key值一样,缓存数据永远只有一条!!!我此时的内心是痛苦的。

有什么方法能让数据缓存不覆盖原来的值,而是加上去?说实话,这里卡了我好久。废话不多说,直接上代码

submit(e) {

const pre_item = wx.getStorageSync(‘attr_item’);

const temp = {

‘goods_name’: wx.getStorageSync(‘goods_name’),

‘memory’: wx.getStorageSync(‘memory’),

‘price’: wx.getStorageSync(‘price’),

‘color’: wx.getStorageSync(‘color’),

‘select_num’: wx.getStorageSync(‘select_num’),

‘cover’: wx.getStorageSync(‘cover’),

‘selected’: false,

‘isTouchMove’: false

}

wx.setStorageSync(‘attr_item’, [temp, …pre_item]); //把获取到的pre_item和temp的数据缓存存入attr_item

wx.showToast({

title: ‘已加入购物车’,

icon: ‘success’,

duration: 3000,

success() {

setTimeout(() => {

wx.navigateBack({

url: “…/goods/show”

});

}, 1000)

}

});

}

商品数量的加减操作

实现思路:分别绑定一个事件来操作商品数量的加减,最后将用户选择的数量设置到数据缓存里。

实现代码:

data: {

select_num: 1 //默认选择为数量为1

},

minusCount(e) { //用户减操作

let select_num = this.data.select_num;

select_num–;

if (select_num < 1) {

return;

}

this.setData({

select_num

});

wx.setStorageSync(‘select_num’, select_num);

},

addCount(e) { //用户加操作

let select_num = this.data.select_num;

select_num++;

if (select_num > 5) {

return;

}

this.setData({

select_num

});

wx.setStorageSync(‘select_num’, select_num);

}

六、购物车操作

页面结构分析:购物车列表用一个弹性布局就搞定。底部的操作栏用固定定位 + 弹性布局就搞定。

购物车还是空的

到小米商城逛逛

<icon type=“{{item.selected?‘success’:‘circle’}}” class=“” color=“#ff6700” size=“20” bindtap=“selectList” data-index=“{{index}}”

/>

<image src=“{{item.cover}}”

mode=“aspectFill” />

{{item.goods_name}} {{item.memory}}

{{item.color}}

{{item.select_num}}×

{{item.price}}

删除

全选

合计:

{{totalPrice}}元

结算

底部操作栏样式

.user-operation{

width: 100%;

height: 100rpx;

line-height: 100rpx;

display: flex;

计算机网络

  • HTTP 缓存

  • 你知道 302 状态码是什么嘛?你平时浏览网页的过程中遇到过哪些 302 的场景?

  • HTTP 常用的请求方式,区别和用途?

  • HTTPS 是什么?具体流程

  • 三次握手和四次挥手

  • 你对 TCP 滑动窗口有了解嘛?

  • WebSocket与Ajax的区别

  • 了解 WebSocket 嘛?

  • HTTP 如何实现长连接?在什么时候会超时?

  • TCP 如何保证有效传输及拥塞控制原理。

  • TCP 协议怎么保证可靠的,UDP 为什么不可靠?

算法

  • 链表

  • 字符串

  • 数组问题

  • 二叉树

  • 排序算法

  • 二分查找

  • 动态规划

  • BFS

  • DFS

  • 回溯算法

  • 15
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值