前言
由于项目很多数据(如图片等)都是从后台调用的,这里给一个API接口文档,但是,我不会讲解怎么在后台写代码,因为这是一个小程序实战,主要学的是怎么去设计一个小程序,至于未来,我会再写一个基于SpringBoot的小程序开发实战的笔记!
1. 效果
2. tabbar底部导航栏
已在上一节(2 | 小程序实战之项目搭建)完成
3. 头部搜索框
由于很多页面都需要使用头部搜索框,所以,为了实现动态化,我们需使用自定义组件
3.1 新增组件
在components文件夹下新增 SearchInput 组件
3.2 声明组件
在需要搜索栏的页面的 json 文件中采用键值对的方式("名字”: “路径”)加入这个自定义组件
index.json
{
"usingComponents": {
"SearchInput":"/components/SearchInput/SearchInput"
},
"navigationBarTitleText": "优选"
}
3.3 引用组件
在页面的 wxml 的文件使用标签名引用自定义组件
index.wxml
<view class="index">
<!-- 搜索框开始 -->
<SearchInput></SearchInput>
<!-- 搜索框结束 -->
</view>
3.4 设计自定义组件
SearchInput.wxml
<view class="search_input">
<navigator url="/pages/search/index" open-type="navigate">
搜索
</navigator>
</view>
SearchInput.less
这里使用less替代wxss,本人觉得这样写比较舒服,可读性好,而且你保存后,开发工具还会自动生成wxss文件,纯属个人喜好
.search_input{
height: 90rpx;
padding: 10rpx;
background-color: var(--themeColor);
navigator{
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: #fff;
border-radius: 15rpx;
color: #666;
}
}
SearchInput.wxss
.search_input {
height: 90rpx;
padding: 10rpx;
background-color: var(--themeColor);
}
.search_input navigator {
height: 100%;
display: flex;
background-color: #fff;
justify-content: center;
align-items: center;
color: #666;
border-radius: 15rpx;
}
4. 轮播图
4.1 获取轮播图的数据接口
https://api-hmugo-web.itheima.net/api/public/v1/home/swiperdata
4.2 调用接口
(1)现在首页的index.js文件中创建一个swiperList空数组
data: {
swiperList:[]
},
(2)在onLoad发送异步请求给swiperList空数组赋值
//Page Object
Page({
data: {
swiperList:[]
},
//options(Object)
onLoad: function(options) {
var reqTask = wx.request({
url: 'https://api-hmugo-web.itheima.net/api/public/v1/home/swiperdata',
success: (result) => {
this.setData({
swiperList:result.data.message
})
}
});
}
});
把wx.request其它的属性(data、method等)删除,是因为都有默认值
4.3 解决域名不合法
由于我们调用的接口的域名没有添加到小程序的后台配置中,所以会报域名不合法的错,即没有权限请求接口,以下有两种解决方法(前提你输入了你自己的appId):
(1)勾选不校验合法域名,。。。 但是,要上线的小程序这种方法不可取,因为要上线的小程序域名都得合法
(2)将域名添加到小程序的后台配置(要上线的小程序必须这么做),先登入小程序官网
这里就加入这的合法域名是:
api-hmugo-web.itheima.net/
注意: 保存更改好域名后,要重启微信开发工具才生效
4.4 渲染轮播图
1 swiper标签存在默认的宽度和高度
100% * 150px
2 image标签也存在默认的宽度和高度
320px * 240px
3 设计图片和轮播图
1 先看一下原图的宽高 750 * 340
2 让图片的高度自适应 宽度 等于100%
3 让swiper标签的高度 变成和图片的高一样即可
4 图片标签
mode属性 渲染模式
widthFix 让图片的标签宽高 和 图片标签的内容的宽高都等比例的发生变化
index.wxml
<view class="index">
<!-- 搜索框开始 -->
<SearchInput></SearchInput>
<!-- 搜索框结束 -->
<!-- 轮播图开始 -->
<view class="index_swiper">
<swiper autoplay indicator-dots circular>
<swiper-item wx:for="{{swiperList}}" wx:key="goods_id">
<navigator url="{{item.navigator_url}}">
<image src="{{item.image_src}}" mode="widthFix" />
</navigator>
</swiper-item>
</swiper>
</view>
<!-- 轮播图结束 -->
</view>
.index_swiper{
swiper{
// 可以不写,默认 750rpx = 100%
width: 750rpx;
// swiper的高度要等于原图的高度,
// 否则切换成宽为750px的页面图片无法撑开
height: 340rpx;
image{
// 加入widthFix 高度自适应了不用写
width: 100%;
}
}
}
4.5 使用promise优化原生的请求
如果要嵌套异步请求(如下图),会感到很不直观,而且还不易维护
所以,接下来讲解如何使用promise优化原生的请求,至于为什么,方便啊! 想了解更多的promise知识点,见参考文档1 参考文档2
实现步骤:
(1)在request文件夹的index.js下创建promise对象
// export代表导出promise对象(这里指request变量名)
export const request=(params)=>{
// 创建一个Promise对象
// resolve,reject 是 Promise 内置方法
return new Promise((resolve,reject)=>{
// 发起异步请求
wx.request({
// 解构params
// 即...params = url: 'https://api-hmugo-web.省略'
...params,
success:(result)=>{
resolve(result);
},
fail:(err)=>{
reject(err);
}
});
})
}
(2)在首页的index.js中引入上面的文件并使用使用promise的方式发起异步请求
// 引入用来发送请求的方法 一定要把路径补全
import {request} from "../../request/index.js"
Page({
data: {
swiperList:[]
},
//options(Object)
onLoad: function(options) {
// 原生的请求
// wx.request({
// url: 'https://api-hmugo-web.itheima.net/api/public/v1/home/swiperdata',
// success: (result) => {
// this.setData({
// swiperList:result.data.message
// })
// }
// });
// 使用promise优化原生的请求
request({url: 'https://api-hmugo-web.itheima.net/api/public/v1/home/swiperdata'})
.then(result=>{
// 这里 result 函数返回值会传递到request的index.js文件中的 success:(result)=>{ ...}函数中
this.setData({
swiperList:result.data.message
})
})
}
});
5. 分类导航
5.1 获取分类导航的数据接口
https://api-hmugo-web.itheima.net/api/public/v1/home/catitems
5.2 调用接口
(1)现在首页的index.js文件中创建一个 cateList 空数组
data: {
swiperList:[],
cateList:[]
},
(2)发送异步请求给cateList空数组赋值
// 引入用来发送请求的方法 一定要把路径补全
import {request} from "../../request/index.js"
Page({
data: {
swiperList:[],
cateList:[]
},
//options(Object)
onLoad: function(options) {
// 使用promise优化原生的请求
this.getSwiperList();
this.getCateList();
},
// 获取轮播图数据
getSwiperList(){
request({url: 'https://api-hmugo-web.itheima.net/api/public/v1/home/swiperdata'})
.then(result=>{
// 这里 result 相当于request的index.js文件中的 success:(result)=>{
this.setData({
swiperList:result.data.message
})
})
},
//获取导航栏数据
getCateList(){
request({url:"https://api-hmugo-web.itheima.net/api/public/v1/home/catitems"})
.then(result=>{
this.setData({
cateList:result.data.message
})
})
}
});
5.3 渲染分类导航
index.wxml
<view class="index">
<!-- 搜索框开始 -->
<SearchInput></SearchInput>
<!-- 搜索框结束 -->
<!-- 轮播图开始 -->
<view class="index_swiper">
<swiper
autoplay
indicator-dots
circular
>
<swiper-item wx:for="{{swiperList}}" wx:key="goods_id">
<navigator url="{{item.navigator_url}}">
<image src="{{item.image_src}}" mode="widthFix" />
</navigator>
</swiper-item>
</swiper>
</view>
<!-- 轮播图结束 -->
<!-- 导航栏开始 -->
<view class="index_cate">
<navigator
wx:for="{{cateList}}"
wx:key="name"
url="pages/category/index"
open-type="navigate"
>
<image src="{{item.image_src}}" mode="widthFix" />
</navigator>
</view>
<!-- 导航栏结束 -->
</view>
index.less
.index_cate{
display: flex;
navigator{
padding: 20rpx;
flex: 1;
image{
// 由于image并没有继承 navigator 的布局
// 所以这里设置 width: 100%; 继承父组件的大小
width: 100%;
}
}
6. 楼层
6.1 获取楼层的数据接口
https://api-hmugo-web.itheima.net/api/public/v1/home/floordata
6.2 调用接口
(1)现在首页的index.js文件中创建一个 floorList 空数组
data: {
swiperList:[],
cateList:[],
floorList:[]
},
(2)发送异步请求给floorList空数组赋值
// 引入用来发送请求的方法 一定要把路径补全
import {request} from "../../request/index.js"
Page({
data: {
swiperList:[],
cateList:[],
floorList:[]
},
//options(Object)
onLoad: function(options) {
// 原生的请求
// wx.request({
// url: 'https://api-hmugo-web.itheima.net/api/public/v1/home/swiperdata',
// success: (result) => {
// this.setData({
// swiperList:result.data.message
// })
// }
// });
// 使用promise优化原生的请求
this.getSwiperList();
this.getCateList();
this.getFloorList()
},
// 获取轮播图数据
getSwiperList(){
request({url: 'https://api-hmugo-web.itheima.net/api/public/v1/home/swiperdata'})
.then(result=>{
// 这里 result 相当于request的index.js文件中的 success:(result)=>{
this.setData({
swiperList:result.data.message
})
})
},
//获取导航栏数据
getCateList(){
request({url:"https://api-hmugo-web.itheima.net/api/public/v1/home/catitems"})
.then(result=>{
this.setData({
cateList:result.data.message
})
})
},
//获取楼层数据
getFloorList(){
request({url:"https://api-hmugo-web.itheima.net/api/public/v1/home/floordata"})
.then(result=>{
this.setData({
floorList:result.data.message
})
})
},
});
6.3 渲染楼层
这里有点难度,渲染楼层涉及嵌套循环
index.wxml
<!-- 楼层开始 -->
<view class="index_floor">
<view
class="floor_group"
wx:for="{{floorList}}"
wx:key="floor_title"
wx:for-item="item1"
wx:for-index="index1"
>
<!-- 标题 -->
<view class="floor_title">
<image src="{{item1.floor_title.image_src}}" mode="widthFix" />
</view>
<!-- 内容 -->
<view class="floor_list">
<navigator
wx:for="{{item1.product_list}}"
wx:key="name"
wx:for-item="item2"
wx:for-index="index2"
url="{{item2.navigator_url}}"
>
<image mode="widthFix" src="{{item2.image_src}}" />
</navigator>
</view>
</view>
</view>
<!-- 楼层结束 -->
index.less
.index_floor{
.floor_group{
.floor_title{
image{
width: 100%;
}
}
.floor_list{
// 内容会被修剪,并且其余内容不可见
overflow: hidden;
navigator{
// 左对齐让它们在一行上放
float: left;
width: 33.33%;
image{
width: 100%;
}
}
}
}
}
这样还不完美,后四个超链接的图片高度应该与第一张图片高度一致,每张图片的高度,应该是第一张图片的一半,继续优化 👇👇👇
index.wxml
<!-- 楼层 开始 -->
<view class="index_floor">
<view
class="floor_group"
wx:for="{{floorList}}"
wx:for-item="item1"
wx:for-index="index1"
wx:key="floor_title"
>
<!-- 标题 -->
<view class="floor_title">
<image mode="widthFix" src="{{item1.floor_title.image_src}}"></image>
</view>
<!-- 内容 -->
<view class="floor_list">
<navigator
wx:for="{{item1.product_list}}"
wx:for-item="item2"
wx:for-index="index2"
wx:key="name"
url="{{item2.navigator_url}}"
>
<image mode="{{index2===0?'widthFix':'scaleToFill'}}" src="{{item2.image_src}}"></image>
</navigator>
</view>
</view>
</view>
<!-- 楼层 结束 -->
index.less
.index_floor{
.floor_group{
.floor_title{
padding: 10px 0;
image{
width: 100%;
}
}
.floor_list{
// 内容会被修剪,并且其余内容不可见
overflow: hidden;
navigator{
// 左对齐让它们在一行上放
float: left;
width: 33.33%;
// 后四个超链接 +? 代表 后?张图片
&:nth-last-child(-n+4){
// 先看第一张图片的原图宽高 232*386
// 232 / 386 = 33.33vw / height
// 第一张图片高度 height = 33.33vw * 386 / 232
// 则后四个超链接的高度为
height: 33.33vw * 386 / 232 / 2;
border-left: 10rpx solid #fff;
}
/* 2 3 两个超链接 */
&:nth-child(2),
&:nth-child(3){
border-bottom: 10rpx solid #fff;
}
image{
width: 100%;
// 继承父组件的高度
height: 100%;
}
}
}
}
}
至此首页的设计已弄完 🤮🤮(让我干呕一下)