3 | 小程序实战之首页设计(tabbar + 头部搜索框+ 轮播图 + 使用promise优化原生的请求 + 分类导航 + 楼层)

前言

由于项目很多数据(如图片等)都是从后台调用的,这里给一个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%;
        }
      }
    }
  }
}

在这里插入图片描述
至此首页的设计已弄完 🤮🤮(让我干呕一下)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值