优购商城项目 详细步骤流程

一、准备的工作

1.文档

  1. 写项目之前必须要有接口文档 准备工作接口文档是必不可少的
  2. 参考文档我们还可以参考 小程序的开发文档、阿里巴巴字体 iconfont 、mdn…

2.项目的搭建

1.搭建项目目录的结构 相当于分模块的去放我们需要的文件 使项目的结构可以清晰明了

2.然后就是分析页面 搭建项目基本项目的页面 (有语义化的 名字可以很方便我们后期的维护 习惯的养成)

{"pages": [    //项目页面的路由信息"pages/index/index","pages/category/index",]}

引入项目中需要的字体图标库 并且可以保证全局引入 这样才可以在所有的页面使用

- 打开阿⾥巴巴字体图标 ⽹站. 选择的图标 . 添加⾄项⽬ . 下载到本地 . 将样式⽂件 由 css 修改为 wxss . 在app.wxss⼩程序中引⼊


页面使用图标 对应的图标名称

3.项目的搭建

4.搭建项目的tabber 结构 参考 小程序 API 文档

5.请求数据的接口进行封装 这样就可以 不必要的重复的代码 http文件去封装

三个部分:
0ne:api.js ------------放接口地址集合 统一的整体的来管理

  • module.exports={}导出 有多个地址 对象的形式导出

two:fach.js ----------------封装微信 网络请求模块 导出一个promis 实例对象 会接收三个形参 (url,data,method)
分别是 请求的路径、请求数据的参数、请求数据的方法
promis对象中的(resolve, reject) 分别代表成功和失败之后执行的回调函数

  • 导出一个 Promise 对象实例 里面封装接口请求的方法用来重复使用

三、http.js --------- 封装请求的方法 首先需要 引入 fach.js 和 api.js 这样才可以进行完美的封装

  • 为了减少重复 无用的代码 可设置基本路径的地址 baseUrl
    接口的理解 api ---- 接口 h8------ 版本号

let baseUrl = “https://api-hmugo-web.itheima.net/api/public/v1”

然后就是定义函数 分别请求对应的接口

需要值得注意的是 必须要在全局的app.js 中 全局的引入http 并且 全局的导出 这样在需要的页面 引入 才可以使用它获取
到数据 否则就会报错

到这里 差不多项目的基本准备工作就差不多真被完毕了 接下来就是 分析 各个页面之间的联系 并且 对组件进行拆分和封装

二、单个页面的逻辑 组件的拆分

1.首页页面

是我们看到的home 首页 搜索、轮播图、导航、和楼层都可以进行封装
子组件我们注册在 components 中
另外可以根据页面 json 中的

 {"component": true,   //来判断当前组件是否是子组件"usingComponents": {}
}

我们在home 父组件页面 请求到轮播图的数据 首先 在api.js 中定义好 轮播图数据的路径
然后在http.js 中 请求数据 接口不需要参数的话就 不写参数 为空 请求的方法为get 统一导出后 在 父组件
home.js 中 我们要全局的引入我们封装的请求方法

* 生命周期函数--监听页面加载  的时候请求数据onLoad: function (options) {// 请求轮播图数据// /home/swiperdataapp.http.banner().then(res => {// console.log(res)数据保存到data中  this.setData({banner: res.data.message})})

并且需要我们传递给子组件

<!-- 轮播图的组件 -->
<w-swiper list="{{banner}}"></w-swiper>
<!-- 轮播图的组件 -->

使用自定义属性的方法
在子组件js来接收数据

properties:{list:{type:Array
}
}

接收数据 并且可以 定义数据类型 和默认数据

然后在页面中渲染我们接受到的数据

 <swiper autoplay="true" indicator-dots="true" indicator-color="pink" class="tops-s">  <block wx:for="{{list}}" wx:key="index"><swiper-item><image src="{{item.image_src}}"></image></swiper-item>
</block>
</swiper>

可以参考 小程序API 文档来对
来实现轮播图的效果 导航部分 和 楼层部分也是一样的流程 父传子 只需要
对页面进行css的样式进行修改

2.分类页面

首先一眼页面是分为左右两部分 右边是侧边导航 左边是数据的渲染 也是一个二级导航的效果 首先根据接口 请求到数据

数据拿到之后进分析 只有对数据最够 明白才能让我们更快更好的的完成页面
这边 拿到的数据是 先渲染左边的侧边导航栏 然后我们给侧边导航地每一项一个点击事件 change

  <view class="lefts" wx:for="{{srot}}" wx:key="index"><view  bindtap="change" data-index="{{index}}">{{item.cat_name}}</view>
</view>

并且使用自定义属性 data-index="{{index}}" 把他的下标传递过去
在js 页面

  // 方法change(e) {// 保存点击的下标    ---this.setData({i: e.currentTarget.dataset.index});// 根据 保持的·下标来获取右边的数据this.setData({tabs: this.data.srot[this.data.i].children})// tabs:this.data.srot[this.data.i].children[0].children// console.log(this.data.tabs);

},
通过e 事件源 来保存下来 我们点击的每一项数据的下标

然后 把符合当前下标的数据 的children 中的数据保存下来 这样就可以实现 点击左边的哪一项 切换到哪一项的数据 了,因为
拿到的数据结构就是 每一下项数据里面都有自己的children 右边展示的也是根据左边的数据而展示他的children的

3.列表页面

<!-- 右边的部分图 -->
<view class="con" wx:for="{{item.children}}"
wx:key="index"   data-cid="{{item.cat_id}}" bindtap="gotolist">

```css<data-cid="{{item.cat_id}}" 自定义属性 保存 一下需要的cid

给每一项的数据一个点击事件 然后 同样保存 代表每一项的cat_id 并给每一项一个点击事件 gotolist

  // 点击跳转gotolist(e) {// console.log(e)// 保存 自己定义的属性 从事件源里获取  let cid = e.currentTarget.dataset.cid;// 页面跳转 把保存 的 cid 参数到另一个页面 使用 wx.navigateTo({url:'/pages/goods_list/goods_list?cid=' + cid,})},

在页面跳转的时候 吧 保存来的 cat_cid 保存下来 并且 使用 字符串拼接的形式 传递参数 到 列表页面

通过(options) 吧参数保存下来 然后在请求 页面数据的时候 携带参数 这样才可以 获取到 数据 最后进行数据的渲染即可

  /*** 生命周期函数--监听页面加载*/// options 获取 需要接受的数据  onLoad: function (options) {console.log(options)// 保存一下动态的cidthis.Paramsztt.cid = options.cid;// console.log(options);// 请求到的数据    参数信息------必须按照接口来写    {参数的位置 不需要参数默认是空 需要的话是对象形式的传递参数 }// pagenum ---请求到的页码    pagesize---请求到的每页多少条数据// 保存下餐数信息// 请求接口里的数据  app.http.shoplist(this.Paramsztt).then(res => {console.log(options)// 获取 总条数const total = res.data.message.total;console.log(total)// 计算总页数this.data.totalPages = Math.ceil(total / this.Paramsztt.pagesize);console.log(total);console.log(this.Paramsztt.pagesize);console.log(this.data.totalPages)// 拼接了数组// this.setData({//   // shoplist: [...this.data.shoplist, ...res.goods]// })this.setData({// 保存获取到的数据 哈哈哈哈shoplist: res.data.message.goods})})},

下拉刷新

/*** 页面相关事件处理函数--监听用户下拉动作*/// 下拉的事件onPullDownRefresh() {// 1 重置数组this.setData({shoplist: []}),// 2 重置页码this.Paramsztt.pagenum = 1;// 3 发送请求// 请求接口里的数据  app.http.shoplist(this.Paramsztt).then(res => {// console.log(options)// 获取 总条数const total = res.data.message.total;console.log(total)// 计算总页数this.data.totalPages = Math.ceil(total / this.Paramsztt.pagesize);console.log(total);console.log(res)console.log(this.Paramsztt.pagesize);console.log(this.data.totalPages)// 拼接了数组// this.setData({//   shoplist: [...this.data.shoplist,]// }),this.setData({// 保存获取到的数据 哈哈哈哈shoplist: res.data.message.goods// 需要来拼接的数据})// })wx.stopPullDownRefresh()// this.getGoodsList();},

///下拉 数据 重新的返回第一页数据

 /*** 页面上拉触底事件的处理函数*/onReachBottom: function () {// 先判断还有几页数据// 如果当前的页面大于总条数if (this.Paramsztt.pagenum >= this.totalPages) {// 就显示没有下一页的数据wx.showToast({title: '没有下一页了',})} else {// 还有下一页数据this.Paramsztt.pagenum++;// 请求接口里的数据  app.http.shoplist(this.Paramsztt).then(res => {// console.log(options)// 获取 总条数const total = res.data.message.total;console.log(total)// 计算总页数this.data.totalPages = Math.ceil(total / this.Paramsztt.pagesize);// console.log(total);console.log(res)// console.log(this.Paramsztt.pagesize);// console.log(this.data.totalPages)// 拼接了数组// this.setData({//   shoplist: [...this.data.shoplist,]// }),// this.setData({//   // 保存获取到的数据 哈哈哈哈//   shoplist:res.data.message.goods// })})// this.getGoodsList();}},

4.详情页面

循环shoplist 数据
<view wx:for="{{shoplist}}" wx:key="index" class="box"
bindtap="gotodetail" data-goods_id="{{item.goods_id}}">

点击的时候吧每一项的goods_id 保存下来 然后传给详情页

// 跳转到 详情页gotodetail(e) {// console.log(ad)// console.log(e.currentTarget.dataset.goods_id)let i = e.currentTarget.dataset.goods_idwx.redirectTo({url: '/pages/goods_detail/goods_detail?goods_id=' + i,})this.setData({i: e.currentTarget.dataset.goods_id})},

在详情页面

  * 生命周期函数--监听页面加载*/onShow: function () {// 获取本地数据里的 数据this.obj.cart = wx.getStorageSync('cart') || [];// // getGoodsDetail// let pages = getCurrentPages();// let currentPage = pages[pages.length - 1];// let options = currentPage.options;// const { goods_id } = options;// // this.getGoodsDetail(goods_id);},// 请求的数据保存携带的参数  使用的是封装的方法// onLoad 的时间段onLoad: function (options) {console.log(options);// 保存点击传过来的id this.setData({id: options.goods_id})//  console.log(this.data.id);// 请求数据  携带保存的参数 app.http.detail({ goods_id: this.data.id }).then(res => {console.log(res)// this.goodsObj=res.data.messagethis.setData({//保存获取到的详情的信息 GoodsInfo: res.data.message,// 保存一个对象  用来添加字段// goodsObj:res.data.message});console.log(this.data.GoodsInfo)// 获取缓存中的商品收藏的数组let collect = wx.getStorageSync("collect") || []// 判断是否被收藏数据let isCollect = collect.some(v => v.goods_id == this.GoodsInfo.goods_id);})},

5.购物车页面

// 添加购物车handleCartAdd() {//console.log(this.data.GoodsInfo)let k = false;// 保存let price = this.data.GoodsInfo.goods_price;let image = this.data.GoodsInfo.goods_small_logo;console.log(image);let flag = false;// 选中的状态let num = 1;let name = this.data.GoodsInfo.goods_name;let id = this.data.GoodsInfo.goods_id;// 循环this.obj.cart.forEach(item => {if (item.id == id) {k = true;item.num++}})if (!k) {// 直接push 一个对象 存到 购物车的数组中去数据 this.obj.cart.push({price,image,flag,num,name,id})}console.log(this.obj.cart);// 存到本地存储wx.setStorageSync('cart', this.obj.cart);// 提示弹窗wx.showToast({title: '加入成功',icon: 'success',//     // true 防止用户 手抖 疯狂点击按钮 mask: true//     // 无语可可可可可})},

6.收藏页面

// 点击 商品收藏图标  有问题// handleCollecthandleCollect() {// 定义图标的变量 一开始是 false 状态let isCollect = false;// 1 获取缓存中的商品收藏数组 没有就是空数组  let collect = wx.getStorageSync("collect") || [];// 2 判断该商品是否被收藏过    findIndex  查找 是否存在这一项  如果存在就返回下边  // 如果不存在就返回 -1 // index 保存下来     循环遍历拿到本地数组的每一项  let index = collect.findIndex(v => v.goods_id === this.GoodsInfo.goods_id);// 3 当index!=-1表示 已经收藏过 if (index !== -1) {// 能找到 已经收藏过了  在数组中删除该商品   collect.splice(index, 1); // 并且商标颜色 变为 灰色isCollect = false;wx.showToast({title: '取消成功',icon: 'success',mask: true});} else {// 没有收藏过collect.push(this.GoodsInfo);isCollect = true;wx.showToast({title: '收藏成功',icon: 'success',mask: true});}// 4 把数组存入到缓存中  本地的缓存中  并且名字叫 setStorageSync wx.setStorageSync("collect", collect);// 5 修改data中的属性  isCollectthis.setData({isCollect})}
})

7.客服、分享页面

 <view class="iconfont icon-kefu"></view><view>客服</view><button open-type="contact"></button></view><view class="tool_item"><view class="iconfont icon-yixianshi-"></view><view>分享</view><button open-type="share"></button></view>

8.结算的页面

全选 判断

 // 全选  上面控制下面的数据checkAll(e) {// console.log(e)// 判断 if (this.data.active == true) {this.data.cart.forEach(item => {item.flag = false;})this.data.active = false}// 选中的要放在新的本地数据的数组里面else {this.data.cart.forEach(item => {item.flag = true;})this.data.active = true}// 保存确定过状态后的数据状态this.setData({cart: this.data.cart,active: this.data.active});// 判断购物车里的数据是否是选中的状态  支付页面需要使用// 只展示的是选中过的数据console.log(this.data.cart);this.maxprice()},

复选框的全选

  // 全选changebox(e) {console.log(e)let that = thislet ids = e.detail.value;that.data.cart.forEach(item => {item.flag = false;});ids.forEach(i => {that.data.cart.forEach((item, index) => {if (item.id == i) {that.data.cart[index].flag = true;}})})// 单选let arrLength = ids.length// let shopLength = that.data.cart.length// 判断if (arrLength == shopLength) {that.setData({active: true,})} else {that.setData({active: false})}this.maxprice()},

根据选中的状态来计算总价

//计算总价maxprice() {let arr = this.data.cart.filter(item => {return item.flag == true})let num = arr.length// 初始数据let price = 0arr.forEach(item => {price = price + item.num * item.price})this.setData({sum: price,num: num})},

数据的数量加和减

  // 加加加jia(e) {let id = e.currentTarget.dataset.id// console.log(this.data.id)// 判断数据 是否是和当前点击的数据一致,一致就让他减减this.data.cart.forEach((item, index) => {if (item.id == id) {item.num++;// 判断减不能为零}})this.setData({cart: this.data.cart})// this.maxprice()},// 减减减jian(e) {// console.log(this.data.cart)let id = e.currentTarget.dataset.idthis.data.cart.forEach((item, index) => {// 判断数据 if (item.id == id) {item.num--;}})this.setData({cart: this.data.cart})// console.log(e)this.maxprice()},

数据每发生一次变化都需要 对总价进行调用

9.获取地址页面

 <!-- 当收货地址 不存在 按钮显示  对象 空对象 bool类型也是true  --><view class="address_btn" wx:if="{{!address.userName}}" class="shou"><view class="add" bindtap="add"> + 获取收货地址</view></view>

// 收货地址 的方法 使用chooseAddress 微信小程序的内置的方法

  add() {wx.chooseAddress({success: (result) => {console.log(result)this.setData({address: result})// 存到本地存储wx.setStorageSync('address', this.data.address)console.log(this.data.address)// let address = result// address.all = address},})},

10.支付页面

1、点击 支付**

>  async handleOrderPay() {
>     try {
>       // 判断缓存中有没有token
>       const token = wx.getStorageSync("token");

2 、没有用户就跳转**

  if (!token) {wx.navigateTo({url: '/pages/auth/index'});return;}

3 、创建订单**

  3.1 准备 请求头参数

// const header = { Authorization: token };
3.2 准备 请求体参数

  const order_price = this.data.totalPrice;const consignee_addr = this.data.address.all;const cart = this.data.cart;let goods = [];cart.forEach(v => goods.push({goods_id: v.goods_id,goods_number: v.num,goods_price: v.goods_price}))const orderParams = { order_price, consignee_addr, goods };

4 、准备发送请求 创建订单 获取订单编号**

 const { order_number } = await request({ url: "/my/orders/create", method: "POST", data: orderParams });

5 、发起 预支付接口**

  const { pay } = await request({ url: "/my/orders/req_unifiedorder", method: "POST", data: { order_number } });

6、 发起微信支付**

  await requestPayment(pay);

7、查询后台 订单状态**

>       const res = await request({ url: "/my/orders/chkOrder", method: "POST", data: { order_number } });
>
>       await showToast({ title: "支付成功" });

8、手动删除缓存中 已经支付了的商品**

>   let newCart=wx.getStorageSync("cart");
> newCart=newCart.filter(v=>!v.checked);   wx.setStorageSync("cart",
> newCart);

9、支付成功了 跳转到订单页面*

>      wx.navigateTo({>         url: '/pages/order/index'
>       });
>
>     } catch (error) {>       await showToast({ title: "支付失败" })
>       console.log(error);
>     }   }

11. 微信小程序的授权登录

// 小程序授权登录 流程 (auth)
例如

1、首先 获取用户信息

const { encryptedData, rawData, iv, singature } = e.detail;

2、获取小程序 登录成功后的code

const { code } = await login();

// 保存到一个对象中获取到的用户的参数信息

const loginParams = { encryptedData, rawData,
iv, signature, code };

3、发送请求 获取用户信息

const { token } = await request({ url: "/users/wxlogin", data: loginParams, method: "post" });

4、把token 存入缓存中 同时跳回到上一个页面

wx.setStorageSync("token", token);

// 回到 上一页 wx的内置方法

wx.navigateBack({delta: 1
});

// try方法 是跳过报错 直接进入下一步 不会影响代码的执行

// try {}catch(error){// await showToast({ title: "支付失败" })
//  console.log(error)
// }

优购商城项目 详细步骤流程相关推荐

  1. 小程序黑马优购商城项目讲解

    小程序优购商城项目讲解 在我们开始之前 我们需要配好该项目所需要的接口文档以及配好相应的页面,以免在开发过程中会出现遗漏的问题出现. 首先我们要知道优购是分为4部分的 分别为 首页/列表/购物车/我的 ...

  2. 微信小程序--优购商城项目(1)

    文章目录 前言 一.配置uni-app开发环境 1.开发工具--HBuilderX 2.新建uni-app项目 3.把项目运行到微信开发者工具 4.使用Git管理 二.tarBar 1.创建 tabB ...

  3. 微信小程序优购商城项目

    这篇文章主要就是把我写的优购商城进行简单的说明,希望可以对大家有所帮助 1.先配置页面 在app.json中设置所需要的页面路径 2.然后再封装我们需要的组件和wx.request wx.reques ...

  4. 微信小程序--优购商城项目(8)

    文章目录 前言 九.购物车页面 1.商品列表区域 (1)渲染购物车商品列表的标题区域 (2)渲染商品列表区域的基本结构 (3) 为 my-goods 组件封装 radio 勾选状态 (4)为 my-g ...

  5. 微信小程序--优购商城项目(6)

    文章目录 前言 七.商品详情 1.创建 goodsdetail 分支并添加编译模式 2.获取商品详情数据 3.渲染商品详情页的 UI 结构 (1)渲染轮播图区域 (2)实现轮播图预览效果 (3) 渲染 ...

  6. 微信小程序--优购商城项目(4)

    文章目录 前言 五.搜索 1.创建 search 分支 2.自定义搜索组件 (1)自定义 my-search 组件 (2) 通过自定义属性增强组件的通用性 (3)为自定义组件封装 click 事件 ( ...

  7. 品优购商城项目常见BUG解析

    1.(Initializing ProtocolHandler) 端口被占用异常.tomcat重复启动所致.* 信息: Initializing ProtocolHandler ["http ...

  8. 小程序优购商城项目讲解

    1.新建⼩程序项⽬ 填入自己的appid 搭建⽬录结构 styles 存放公共样式 components 存放组件 lib 存放第三⽅库 utils ⾃⼰的帮助库 request ⾃⼰的接⼝帮助库 2 ...

  9. 前端与移动开发----购物商城案例(品优购PC项目上)

    品优购项目-上 目标 能够遵循品优购代码规范 能够在品优购首页中引入 favicon 图标 能够说出三大标签 SEO 优化 能够在品优购首页中使用字体图标 能够说出 LOGO 需要哪些 SEO 优化 ...

最新文章

  1. org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 19
  2. 数据中心柴油发电机组功率
  3. TypeScript 入门
  4. 连接excel执行Insert Into语句出现“操作必须使用一个可更新的查询”的解决
  5. 百度Ueditor编辑器wordimage踩坑
  6. 基于jQuery日历插件制作日历
  7. [原创]网银在线chinabank安全漏洞之“不完善的开发软件包”
  8. 金蝶kis云触发器解决审核和反审核的问题
  9. 前端小技巧之ajax后遍历生成相同结构不同数据的dom
  10. java 读取wav采样数据_读取wav文件中的音频数据操作
  11. matlab汉明窗dft,Mitre_sfr代码注解(四) LSF / 汉明窗 / SFR(DFT)计算
  12. DMB DSB和ISB区别
  13. 解决引用百度地图点击详情无法定位到相应位置问题
  14. KiTTY/cnKiTTY与PuTTY/cnPuTTY差异和使用的简单说明~~
  15. matplotlib | Python强大的作图工具,让你从此驾驭图表
  16. Ubuntu 15.10 搜狗搜狗输入法崩溃解决方法
  17. NGR-PEG-6-FAM 肿瘤新生血管靶向肽NGR-聚乙二醇-6-羧甲基荧光素
  18. 索尼前CEO平井一夫今日正式退休 结束35年索尼生涯
  19. 【论文精读】KD-MVS
  20. Pycharm Professional(专业版)完美破解,永久激活

热门文章

  1. 【2018国赛线上初赛】知识问答题真题演练第三波
  2. 政务综合服务平台建设项目方案书
  3. 微信小程序开发笔记 支付篇②——微信小程序通过小程序云实现微信支付功能
  4. 道客巴巴文档下载方案
  5. CAD想要快速绘图的基本技巧
  6. 微信企业号开发(6)--发送消息
  7. 爬取隔壁杭电研究生导师信息
  8. 赌场式交易策略:成功的交易系统要像赌场一样 赚那些赌徒的钱
  9. Failed to connect to github.com port 443: Operation timed out
  10. 视频监控三大标准比较 ONVIF不负众望