小程序项目——黑马优购

1. 起步

  • 1)uni-app框架:本项目用的是uni-app框架进行开发的,因为uni-app框架是使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到 iOS、Android、H5、以及各种小程序、快应用等多个平台。
  • 2)开发工具:用HBuilderX 来开发,因为uni-app项目都是用HbuildX来开发HBuilderX官网
  • 3)sass编译:为了方便编写scss/sass样式,建议安装 scss/sass 编译插件下载地址;进入之后点击——使用 HBuilderX 导入插件,登入HBuilderX,进行下载
  • 4)新建项目
    • ① 文件 ==》 新建 ==》 项目
    • ② 填写项目的一些基本的信息
      在这里插入图片描述
  • 5)uni-app项目目录结构
    在这里插入图片描述
  • 6)项目运行到微信开发者工具
    • ① 填写自己的微信小程序的 AppID:manifest.json文件中 ==》 选择微信小程序配置 ==》 再填写微信小程序ID
    • ② 在 HBuilderX 中,配置“微信开发者工具”的安装路径:工具 ==》 设置 ==》 运行设置 ==》 再填写微信开发者工具的存放路径
    • ③ 开启微信开发者者工具的“服务端口”:设置 ==》 安全 ==》 服务端口开启
    • ④ Hbuildx中:运行 ==》 运行到小程序模拟器 ==》 微信开发者工具;
    • 作用:将当前项目运行到微信开发者工具中,是为了方便查看项目的效果,代码编辑还是在HBuilderX中
  • 7)使用git管理项目
    • ① 项目根目录中创建.gitignore忽略文件:用来忽略一些不需要版本管理的文件
      在这里插入图片描述

    • ② unpackage目录下创建.gitkeep文件进行占位:因为忽略掉了unpackage里的唯一一个文件dist,unpackage也不会被git追踪,所以

    • ③ 初始化本地仓库:git init / git add . / git commit -m '初始化项目'

    • ④ 创建远程仓库,把本地仓库和远程仓库进行关联

2. tabBar页面

在这里插入图片描述

  • 1)创建tabBar分支git checkout -b tabBar
  • 2)创建tabBar页面
    • ① 在pages右键新建页面 ⇒ 依次创建home、cate、cart、my页面
    • ② 新建每个页面时有如下配置:css样式用的是scss
      在这里插入图片描述
  • 3)页面新建成功:pages.json文件中 ⇒ pages节点中生成每个tabBar页面的页面路径
  • 4)配置tabBar效果:pages.json文件 ⇒ 配置tabBar节点。代码和在微信开发者工具中的配置是一样的
   "tabBar": {
       "selectedColor": "#C00000",  // 选中tab栏文本颜色
       "list": [
         {
           "pagePath": "pages/home/home",
           "text": "首页",
           "iconPath": "static/tab_icons/home.png",
           "selectedIconPath": "static/tab_icons/home-active.png"
         },
         {
           "pagePath": "pages/cate/cate",
           "text": "分类",
           "iconPath": "static/tab_icons/cate.png",
           "selectedIconPath": "static/tab_icons/cate-active.png"
         },
         {
           "pagePath": "pages/cart/cart",
           "text": "购物车",
           "iconPath": "static/tab_icons/cart.png",
           "selectedIconPath": "static/tab_icons/cart-active.png"
         },
         {
           "pagePath": "pages/my/my",
           "text": "我的",
           "iconPath": "static/tab_icons/my.png",
           "selectedIconPath": "static/tab_icons/my-active.png"
         }
       ]
     }
  • 4)删除默认的index首页:HBuilderx(pages.json中路径代码和pages中的文件夹)和微信开发者工具中的index首页
  • 5)修改导航条样式效果:pages.json文件 ⇒ globalStyle节点(和tabBar同级)
  "globalStyle": {
    "navigationBarTextStyle": "white",
    "navigationBarTitleText": "黑马优购",
    "navigationBarBackgroundColor": "#C00000",
    "backgroundColor": "#FFFFFF"
  }
  • 6)分支的提交与合并
    • ① 进行本地commit提交:git add . / git commit -m "完成了 tabBar 的开发"
    • ② 提交到远程仓库进行保存:git push -u origin tabBar
    • ③ 将tabBar代码合并到主分支:git checkout master / git merge tabBar

3. 首页

  • 首页的代码全部定义在:pages/home/home.vue中
  • 结构定义在template标签中,逻辑定义在script标签中,样式定义在

3.1 创建home分支

  • 首先创建home分支
git checkout home

3.2 配置网络请求

  • 1)传统弊端:axios——小程序不能使用;wx.request()—— 功能太简单,不支持拦截器。
  • 2) 因此:使用@escook/request-miniprogram第三方包,下载使用参考官方文档
  • 3)main.js中进行配置
// 1. 按需导入$http
import { $http } from '@escook/request-miniprogram'
// 2. uni对象上挂载$http(以后就使用uni.$http)
uni.$http = $http
// 3. 配置本项目中的请求的根路径
$http.baseUrl = 'https://www.uinav.com'
// 4. 请求拦截器上加上loading效果
$http.beforeRequest = function (options) {
  uni.showLoading({
    title: '数据加载中...',
  })
}
// 5. 响应拦截器上隐藏loading效果
// 请求完成之后做一些事情
$http.afterRequest = function () {
  uni.hideLoading()
}

3.3 轮播图区域

在这里插入图片描述

3.3.1 获取轮播图的数据

  • 1)data中:定义存放轮播图的数组
  • 2)onLoad生命周期函数中:调用方法
  • 3)methods中:定义获取数据的方法
    • ① 用uni.$http.get 来获取数据
    • ② 用async和await来获取数据,代表值是一个promise对象
    • ③ 判断状态码是否等于200,如果不是的话,调用uni.showToast提示他
    • ④ 为data中数据赋值
export default {
  data() {
    return {
      // 1. 轮播图的数据列表,默认为空数组
      swiperList: [],
    }
  },
  onLoad() {
    // 2. 在小程序页面刚加载的时候,调用获取轮播图数据的方法
    this.getSwiperList()
  },
  methods: {
    // 3. 获取轮播图数据的方法
    async getSwiperList() {
      // 3.1 发起请求
      const { data: res } = await uni.$http.get('/api/public/v1/home/swiperdata')
      // 3.2 请求失败
      if (res.meta.status !== 200) {
        return uni.showToast({
          title: '数据请求失败!',
          duration: 1500,
          icon: 'none',
        })
      }
      // 3.3 请求成功,为 data 中的数据赋值
      this.swiperList = res.message
    },
  },
}

3.3.2 渲染轮播图的UI结构

  • 1)swiper组件:轮播图还是用swiper组件(微信小程序开发工具的用法)
  • 2)v-for循环:循环渲染用Vue的v-for循环,:key用来做唯一标识
  • 3)属性动态绑定:src:图片的路径属性用动态绑定(Vue)
  • 4)css配置:最后美化一下UI结构
<!-- 轮播图区域 -->
    <swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000" :circular="true">
      <!-- 循环渲染轮播图的 item 项 -->
      <swiper-item v-for="(item, i) in swiperList" :key="i">
        <view class="swiper-item">
          <!-- 动态绑定图片的 src 属性 -->
          <image :src="item.image_src"></image>
        </view>
      </swiper-item>
    </swiper>
swiper {
 height: 330rpx;

 .swiper-item,
 image {
   width: 100%;
   height: 100%;
 }
}

3.3.3 配置小程序分包

  • 1)原因:我们把tabBar页面放到主包中,把其他页面放到分包中,减少小程序启动的加载时间
  • 2)配置步骤:项目根目录创建subpkg文件夹 》 pages.json中配置subPackages 节点(和pages同级,用来配置分包结构)==》 在subpkg文件夹上新建页面 ==》 分包处:选择subpkg分包
"subPackages": [
    {
      "root": "subpkg",
      "pages": []
    }
  ]

在这里插入图片描述

3.3.4 点击轮播图跳转到详情页面

  • 1)把包裹图片的view组件 ,改成navigator组件
  • 2)动态绑定url属性进行跳转
<!--动态拼接上参数-->
<navigator class="swiper-item" :url="'/subpkg/goods_detail/goods_detail?goods_id=' + item.goods_id">
    <!-- 动态绑定图片的 src 属性 -->
    <image :src="item.image_src"></image>
</navigator>

3.3.5 封装uni.$showMsg() 方法

  • 1)uni.showToast()用来提示信息 ==》 每次数据请求的时候都要调用 ==》 因此直接封装一个方法
  • 2)在main.js中封装uni.s h o w M s g ( ) , 之 后 再 每 次 调 用 的 时 候 直 接 调 用 ‘ u n i . showMsg() ,之后再每次调用的时候直接调用`uni.showMsg()uni.showMsg`就好
  • 3)uni.$showMsg:title和duration有默认的值,也可以传递数据
uni.$showMsg = function (title = '数据加载失败!', duration = 1500) {
	uni.showToast({
		title,
		duration,
		icon: 'none'
	})
} 

3.4 分类导航区域

在这里插入图片描述

3.4.1 获取分类导航区域的数据

  • 1)data中:定义收集分类导航的数据
  • 2)onLoad中:调用获取分类导航数据的方法
  • 3)methods中:定义获取分类导航数据的方法
    • ① 获取数据:uni.$http.get获取;async和await获取promise对象的数据;数据解构赋值
    • ② 响应状态码:如果不等于200,就return出去,并且调用uni.$showMsg()提示获取失败
    • ③ 给数据赋值
export default {
  data() {
    return {
      // 1. 分类导航的数据列表
      navList: [],
    }
  },
  onLoad() {
    // 2. 在 onLoad 中调用获取数据的方法
    this.getNavList()
  },
  methods: {
    // 3. 在 methods 中定义获取数据的方法
    async getNavList() {
      const { data: res } = await uni.$http.get('/api/public/v1/home/catitems')
      if (res.meta.status !== 200) return uni.$showMsg()
      this.navList = res.message
    },
  },
}                                                                                                                                                                                                                                                                                                                                                                                             

3.4.2 渲染分类导航区域的UI结构

  • 1)v-for循环渲染数据:还要加:key=“i”,唯一性;每一项图片用view组件包裹
  • 2)图片css样式:图片设定宽高 + 父级盒子设定(display:flex)让他同一行显示
<view class="nav-list">
   <view class="nav-item" v-for="(item, i) in navList" :key="i">
     <image :src="item.image_src" class="nav-img"></image>
   </view>
</view>
/* scss样式可以用包裹 */ 
.nav-list {
  display: flex;
  /* 均分区域 */ 
  justify-content: space-around;
  margin: 15px 0;

  .nav-img {
    width: 128rpx;
    height: 140rpx;
  }
}

3.4.3 点击分类图标跳转到分类页面

  • 1)给图片每一项绑定事件处理函数
  • 2)在methods中定义事件处理函数
  <view class="nav-item" @click="navClickHandler(item)">
    <image :src="item.image_src" class="nav-img"></image>
  </view>
methods: {
	navClickHandler(item)  {
		// 首先判断它是不是分类那一项,判断他的名字是不是叫分类
		if (item.name ===  '分类') {
		// 如果是的哈进行跳转
			uni.switchTab({
				url: '/pages/cate/cate'
			})
		}
	}
}

3.5 楼层区域

在这里插入图片描述

3.5.1 获取楼层数据

  • 1)data中:定义收集分类导航的数据
  • 2)onLoad中:调用获取分类导航数据的方法
  • 3)methods中:定义获取分类导航数据的方法
    • ① 获取数据:uni.$http.get获取;async和await获取promise对象的数据;数据解构赋值
    • ② 响应状态码:如果不等于200,就return出去,并且调用uni.$showMsg()提示获取失败
    • ③ 给楼层数据赋值
export default {
  data() {
    return {
      // 1. 楼层的数据列表
      floorList: [],
    }
  },
  onLoad() {
    // 2. 在 onLoad 中调用获取楼层数据的方法
    this.getFloorList()
  },
  methods: {
    // 3. 定义获取楼层列表数据的方法
    async getFloorList() {
      const { data: res } = await uni.$http.get('/api/public/v1/home/floordata')
      if (res.meta.status !== 200) return uni.$showMsg()
      this.floorList = res.message
    },
  },
}

3.5.2 渲染楼层的标题

  • 1)楼层的标题:其实也是一张图片,所以我们要做的就是把图片渲染出来
  • 2)在楼层的每一项里面:用v-for进行循环渲染楼层数据
  • 3)楼层标题:动态绑定数据的floor_title中的图片地址
<!-- 楼层区域 -->
<view class="floor-list">
  <!-- 楼层 item 项 -->
  <view class="floor-item" v-for="(item, i) in floorList" :key="i">
    <!-- 楼层标题 -->
    <image :src="item.floor_title.image_src" class="floor-title"></image>
  </view>
</view>
.floor-title {
  height: 60rpx;
  width: 100%;
}

3.5.3 渲染楼层里面的图片

在这里插入图片描述

  • 1)图片布局:左边一个大盒子(放一张图片)+ 右边一个盒子(放四张图片)
  • 2)UI结构:我们先把图片数据给渲染出来
    • ① 结构:图片区域一个盒子包裹 + 左侧图片一个盒子包裹 (里面放image组件)+ 右侧图片盒子包裹(图片每一项再用盒子包裹,里面放image组件)
    • ② 左侧图片:图片路径绑定数组项中的product_list中的第一项;宽度也是动态绑定,因为返回值中有宽度;mode设置为widthFix(表示高度适应宽度)
    • ③ 右侧图片:要接着循环遍历一次item.product_list;并且不能显示第一张图片,因此用v-if条件渲染;宽度和mode和第一张图片一样的
<!-- 楼层图片区域 -->
<view class="floor-img-box">
  <!-- 左侧大图片的盒子 -->
  <view class="left-img-box">
    <image :src="item.product_list[0].image_src" :style="{width: item.product_list[0].image_width + 'rpx'}" mode="widthFix"></image>
  </view>
  <!-- 右侧 4 个小图片的盒子 -->
  <view class="right-img-box">
    <view class="right-img-item" v-for="(item2, i2) in item.product_list" :key="i2" v-if="i2 !== 0">
      <image :src="item2.image_src" mode="widthFix" :style="{width: item2.image_width + 'rpx'}"></image>
    </view>
  </view>
</view>
  • 3)css样式
    • ① 右侧图片盒子:flex布局 + 允许元素换行(flex-wrap: wrap)+ 每一项平分空间
    • ② 图片大盒子:flex布局
.right-img-box {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
}

.floor-img-box {
  display: flex;
  padding-left: 10rpx;
}

3.5.4 点击图片跳转到商品列表页

  • 1)新建页面:在subpkg文件夹上右键 ==》 新建商品列表页面
    在这里插入图片描述
  • 2)处理url地址:后台会返回一个要跳转的url地址,但是他的地址,跟我们要跳转的地址不一样
    • ① 后台url地址:/pages/goods_list?携带的参数
    • ② 跳转的地址:/subpkg/goods_list/goods_list?携带的参数
    • ③ 因此我们要给返回值自定义一个属性url:值为——路径+返回的url参数
      • 定义url:图片路径所在的数组,给每一项循环遍历加上自定义属性url
      • url:页面路径 + 参数(返回的数据根据 ——?,进行切割之后的第一项)
// 通过双层 forEach 循环,处理 URL 地址
  res.message.forEach(floor => {
    floor.product_list.forEach(prod => {
      prod.url = '/subpkg/goods_list/goods_list?' + prod.navigator_url.split('?')[1]
    })
  })
	
// 2. 再把值给楼层数据
  this.floorList = res.message
  • 3)把包裹图片的盒子改成——navigator组件,动态绑定url属性进行跳转
<!-- 楼层图片区域 -->
<view class="floor-img-box">
  <!-- 左侧大图片的盒子 -->
  <navigator class="left-img-box" :url="item.product_list[0].url">
    <image :src="item.product_list[0].image_src" :style="{width: item.product_list[0].image_width + 'rpx'}" mode="widthFix"></image>
  </navigator>
  <!-- 右侧 4 个小图片的盒子 -->
  <view class="right-img-box">
    <navigator class="right-img-item" v-for="(item2, i2) in item.product_list" :key="i2" v-if="i2 !== 0" :url="item2.url">
      <image :src="item2.image_src" mode="widthFix" :style="{width: item2.image_width + 'rpx'}"></image>
    </navigator>
  </view>
</view>

3.6 home分支提交

  • 1)home分支本地的commit提交
// 将本地代码提交到暂存区
git add .
// 将暂存区代码提交到仓库
git commit -m "完成了 home 首页的开发"
  • 2)将本地分支提交到远程仓库
git push -u origin home
  • 3 )将home分支合并到主分支
git checkout master
git merge home
  • 4)删除本地的 home 分支
git branch -d home
  • 通过ctrl + E可以选中所有相似的代码,方便多选加class类名
    在这里插入图片描述

版权声明:本文为weixin_46025916原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。