慕尚花坊 --- 首页

0. 首页配置

1. 数据请求 API

1. 定义接口 API 函数

miniprogram/api/index.js

import http from '@/utils/http'

/**
 * @description 获取首页轮播图数据
 */

/**
 * @description 通过并发请求获取首页的数据, 提升页面的渲染速度
 */
export const reqIndexData = () => {
  // 使用 Promise.all() 发送并发请求
  // return Promise.all(http.get('/index/findBanner'), http.get('/index/findCategory1'), http.get('/index/advertisement'), http.get('/index/findListGoods'), http.get('/index/findRecommendGoods'))

  // 使用封装的 http.all() 发送并发请求
  return http.all(http.get('/index/findBanner'), http.get('/index/findCategory1'), http.get('/index/advertisement'), http.get('/index/findListGoods'), http.get('/index/findRecommendGoods'))
}

pages/index/index.js

import {
  reqIndexData
} from '@/api/index'
Page({
  data: {
    bannerList: [], // 轮播图
    categoryList: [], // 商品导航
    activeList: [], // 活动区
    hotList: [], // 热门商品(人气推荐)
    guessList: [] // 猜你喜欢
  },
  // 获取首页数据
  async getIndexData() {
    const res = await reqIndexData()
    this.setData({
      bannerList: res[0].data,
      categoryList: res[1].data,
      activeList: res[2].data,
      hotList: res[3].data,
      guessList: res[4].data,
    })
  },
  // 监听页面的加载
  onLoad() {
    // 在页面加载以后, 调用获取首页数据的方法
    this.getIndexData()
  }
})

2. 全局样式

pages/index/inde.scss

// 整个页面样式
.index-container {
  background-color: #efefef !important;
  position: relative;

  // 首页背景图样式
  .window-bgc {
    position: absolute;
    width: 100%;
    height: 450rpx;
    top: -230rpx;
    border-radius: 30rpx;
    background-color: #f3514f;
  }
}

1. 轮播图组件

0. 效果图

1. 创建组件

1. pages/index/banner 创建组件 banner

2. 当前 index 页面注册 banner 组件

pages/index/index.json

{
  "usingComponents": {
    "banner": "./banner/banner"
  }
}

3. 当前 index 页面使用 banner 组件

pages/index/index.wxml

<!-- 轮播图区 -->
<banner />

2. 页面构建

pages/index/banner/banner.wxml

<!-- 轮播图区 -->
<view class="swiper">
  <swiper autoplay circular indicator-dots interval="5000" indicator-color="#fff" indicator-active-color="#f3514f" class="swiper-warpper">
      <swiper-item class="swiper-item">
          <navigator class="navigator" url="/pages/goods/detail/detail?goodId=id">
              <image class="img" src="../../assets/swipers/swiper-1.jpg" mode="" />
          </navigator>
      </swiper-item>
      <swiper-item class="swiper-item">
          <navigator class="navigator" url="/pages/goods/detail/detail?goodId=id">
              <image class="img" src="../../assets/swipers/swiper-2.jpg" mode="" />
          </navigator>
      </swiper-item>
      <swiper-item class="swiper-item">
          <navigator class="navigator" url="/pages/goods/detail/detail?goodId=id">
              <image class="img" src="../../assets/swipers/swiper-3.jpg" mode="" />
          </navigator>
      </swiper-item>
  </swiper>
</view>

pages/index/banner/banner.scss

// 轮播图样式
.swiper {
  .swiper-warpper{
    height: 360rpx;
    padding: 20rpx 16rpx;
    .swiper-item{
      border-radius: 10rpx;
      .navigator{
        width: 750rpx;
        background-color: lightcoral;
        .img {
          width: 100%;
        }
      }
    }
  }
}

3. 数据交互

1. 将 index 请求回来的数据, 传递到组件 banner 组件内

pages/index/index.wxml

<banner bannerList="{{ bannerList }}" />

2. banner 组件接收数据

pages/index/banner/banner.js

Component({

  /**
   * 组件的属性列表
   */
  properties: {
    bannerList: {
      type: Array,
      value: []
    }   // 接受数据
  },
})

3. 循环从服务器请求回来的数据, 生成页面

pages/index/banner/banner.wxml

<!-- 轮播图区 -->
<view class="swiper">
  <swiper autoplay circular interval="5000" indicator-active-color="#f3514f" bindchange="changeSwiper" class="swiper-warpper">
    <!-- 通过 block 标签对轮播图数据进行循环渲染 -->
    <block wx:for="{{ bannerList }}" wx:key="id">
      <swiper-item class="swiper-item">
        <navigator hover-class="none" class="navigator" url="/pages/goods/detail/detail?category2Id={{ item.id }}">
          <image class="img" src="{{ item.imageUrl }}" mode="" />
        </navigator>
      </swiper-item>
    </block>
  </swiper>
</view>

4. 自定义圆点样式

1. 去除轮播图圆点图标的默认效果,和选中时的颜色

pages/index/banner/banner.wxml

<view class="swiper">
  <swiper 
  autoplay 
  circular 
  interval="5000" 
  indicator-active-color="#f3514f"
   class="swiper-warpper">
    <block wx:for="{{ bannerList }}" wx:key="id">
      <swiper-item class="swiper-item">
        <navigator class="navigator" url="/pages/goods/detail/detail?goodId={{item.id}}">
          <image class="img" src="{{ item.imageUrl }}" mode="" />
        </navigator>
      </swiper-item>
    </block>
  </swiper>

  <!-- 轮播图的面板指示点, 因为面板指示点不支持自定义, 所以只能通过自定义结构的方式 -->
  <view class="indicator">
    <!-- active 类名: 当前被激活的面板指示点颜色 -->
    <!-- cricle 类名: 默认的面板指示点颜色 -->
    <text wx:for="{{ bannerList.length }}" wx:key="id" class="rectangle">
    </text>
  </view>
</view>

pages/index/banner/banner.scss

// 轮播图样式
.swiper {
  position: relative;
  .swiper-warpper {
    height: 360rpx;
    padding: 20rpx 16rpx;
    position: relative;
    z-index: 10;

    .swiper-item {
      border-radius: 10rpx;

      .navigator {
        width: 750rpx;

        .img {
          width: 100%;
        }
      }
    }
  }
  // 圆点样式
  .indicator {
    position: absolute;
    top: 360rpx;
    left: 33.33%;
    z-index: 100;
    display: flex;
    .text {
      margin-right: 20rpx;
      width: 60rpx;
      height: 10rpx;
      z-index: 100;
    }
    .active {
      background-color: #f3514f;
    }
    .rectangle {
      background-color: #fff;
    }
  }
}

pages/index/banner/banner.wxml

<view class="swiper">
  <swiper autoplay circular interval="5000" indicator-active-color="#f3514f" bindchange="changeSwiper" class="swiper-warpper">
    <!-- 通过 block 标签对轮播图数据进行循环渲染 -->
    <block wx:for="{{ bannerList }}" wx:key="id">
      <swiper-item class="swiper-item">
        <navigator class="navigator" url="/pages/goods/detail/detail?category2Id={{ item.id }}">
          <image class="img" src="{{ item.imageUrl }}" mode="" />
        </navigator>
      </swiper-item>
    </block>
  </swiper>

  <view class="indicator">
    <!-- 每次轮播图切换时, 获取到当前轮播图的索引, 跟当前索引对比, 如果一致则添加选中效果 -->
    <text wx:for="{{ bannerList.length }}" wx:key="id" class="{{ index === activeIndex ? 'text active' : 'text rectangle'}}">
    </text>
  </view>
</view>

pages/indx/banner/banner.js

Component({
  data: {
    activeIndex: 0  // 默认为0, 默认选中第一个圆点 
  },
  methods: {
    // 每次轮播图切换时,触发 change 事件
    changeSwiper(event){
      this.setData({
        activeIndex: event.detail.current
      })
    }
  }
})

5. 页面跳转配置

1. 创建 goods 目录及页面

{
  "pages": [
    "pages/goods/goods"
  ]
}

2. 创建 pages/goods/detail 组件

3. 配置 pages/goods/detail组件全局路径

app.json

{
  "pages": [
    "pages/goods/detail/detail"
  ],
}

2. 商品导航区

0. 效果图

1. 创建组件

1. 创建 index/entrance 组件

2. 注册 index/entrance 组件

pages/index/index.json

{
  "usingComponents": {
    "banner": "./banner/banner",
    "entrance": "./entrance/entrance"    // 注册
  }
}

3. 当前 index 页面使用 entrance 组件

pages/index/index.wxml

<!-- 商品导航区 -->
<entrance />

2. 页面构建(字体图标方式)

1. 字体图标 --- 阿里云矢量图标库

https://www.iconfont.cn/

2. 将想要的图标加到项目中

3. 点击 项目设置, 勾选 base64

4. 生成代码后,点击复制代码

5. 在项目根目录下创建 iconfont/iconfont.scss

6. 在 pages/index/entrance/entrance.scss 中导入 iconfont.scss

@import "./iconfont/iconfont.scss";    // 注意一定要分号结尾

7. 页面结构和样式

pages/index/entrance/entrance.wxml

<!-- 快速导航栏 -->
<view class="entrance">
  <view class="entrance-item">
    <navigator class="entrance-nav" url="">
      <text class="iconfont icon-meiguihua"></text>
      <text>鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="">
      <text class="iconfont icon-meiguihua"></text>
      <text>鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="">
      <text class="iconfont icon-meiguihua"></text>
      <text>鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="">
      <text class="iconfont icon-meiguihua"></text>
      <text>鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="">
      <text class="iconfont icon-meiguihua"></text>
      <text>鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="">
      <text class="iconfont icon-meiguihua"></text>
      <text>鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="">
      <text class="iconfont icon-meiguihua"></text>
      <text>鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="">
      <text class="iconfont icon-meiguihua"></text>
      <text>鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="">
      <text class="iconfont icon-meiguihua"></text>
      <text>鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="">
      <text class="iconfont icon-meiguihua"></text>
      <text>鲜花玫瑰</text>
    </navigator>
  </view>
</view>

pages/index/entrance/entrance.scss

@import './iconfont/iconfont.scss';

// 标题快速导航样式
.entrance {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  padding: 16rpx;
  margin: 0 16rpx;
  background-color: #fff;
  border-radius: 10rpx;
  font-size: 24rpx;
  height: 260rpx;

  .entrance-item {
    .entrance-nav {
      width: 120rpx;
      display: flex;
      flex-direction: column;
      align-items: center;

      text {
        &:nth-of-type(2) {
          margin-top: 12rpx;
        }
      }
    }

  }

  // 字体图标样式
  .iconfont {
    font-size: 70rpx;
    color: #efefef;
    background-color: #f3514f;
    border-radius: 25rpx;
  }
}

3. 页面构建(图片方式)

pages/entrance/entrance.wxml

<!-- 快速导航栏 -->
<view class="entrance">
  <view class="entrance-item">
    <navigator class="entrance-nav" url="/pages/good/list/list?category1Id=1">
      <image class="nav-img" src="../../../assets/categorys/cate-1.png"/>
      <text class="nav-text">鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="/pages/good/list/list?category1Id=1">
      <image class="nav-img" src="../../../assets/categorys/cate-1.png"/>
      <text class="nav-text">鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="/pages/good/list/list?category1Id=1">
      <image class="nav-img" src="../../../assets/categorys/cate-1.png"/>
      <text class="nav-text">鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="/pages/good/list/list?category1Id=1">
      <image class="nav-img" src="../../../assets/categorys/cate-1.png"/>
      <text class="nav-text">鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="/pages/good/list/list?category1Id=1">
      <image class="nav-img" src="../../../assets/categorys/cate-1.png"/>
      <text class="nav-text">鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="/pages/good/list/list?category1Id=1">
      <image class="nav-img" src="../../../assets/categorys/cate-1.png"/>
      <text class="nav-text">鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="/pages/good/list/list?category1Id=1">
      <image class="nav-img" src="../../../assets/categorys/cate-1.png"/>
      <text class="nav-text">鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="/pages/good/list/list?category1Id=1">
      <image class="nav-img" src="../../../assets/categorys/cate-1.png"/>
      <text class="nav-text">鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="/pages/good/list/list?category1Id=1">
      <image class="nav-img" src="../../../assets/categorys/cate-1.png"/>
      <text class="nav-text">鲜花玫瑰</text>
    </navigator>
  </view>
  <view class="entrance-item">
    <navigator class="entrance-nav" url="/pages/good/list/list?category1Id=1">
      <image class="nav-img" src="../../../assets/categorys/cate-1.png"/>
      <text class="nav-text">鲜花玫瑰</text>
    </navigator>
  </view>
</view>

pages/index/entrance/entrance.scss

@import './iconfont/iconfont.scss';

// 标题快速导航样式
.entrance {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  padding: 16rpx;
  margin: 0 16rpx;
  background-color: #fff;
  border-radius: 10rpx;
  font-size: 24rpx;
  height: 260rpx;

  .entrance-item {
    .entrance-nav {
      width: 120rpx;
      display: flex;
      flex-direction: column;
      align-items: center;

      .nav-img {
        width: 90rpx;
        height: 90rpx;
      }
    }
    &:nth-child(n+6) {     // 第二排的标签
      margin-top: 25rpx;
    }
  }
}

4. 数据交互

1. 将 index 请求回来的数据, 传递到组件 banner 组件内

pages/index/index.wxml

<entrance categoryList="{{ categoryList }}"/>

2. entrance 组件接收数据

pages/index/entrance/entrance.js

Component({

  /**
   * 组件的属性列表
   */
  properties: {
    categoryList: {
      type: Array,
      value: []
    }   // 接受数据
  },
})

3. 循环生成标签

pages/index/entrance/entrance.wxml

<!-- 快速导航栏 -->
<view class="entrance">
  <view class="entrance-item" wx:for="{{ categoryList }}" wx:key="id">
    <navigator class="entrance-nav" url="/pages/goods/list/list?category1Id={{ item.id }}">
      <image class="nav-img" src="{{ item.imageUrl }}"/>
      <text class="nav-text">{{ item.name }}</text>
    </navigator>
  </view>
</view>

5. 页面跳转配置

1. 创建 pages/goods/list 组件

2. 配置 pages/goods/list组件全局路径

app.json

{
  "pages": [
    "pages/goods/list/list",
  ],
}

3. 活动区

pages/index/index.wxml

<!-- 活动区 -->
<view class="content">
  <view class="left-content">
    <navigator url="/pages/good/list/list?category2Id={{ activeList[0].category2Id }}">
      <image src="{{ activeList[0].imageUrl }}" mode="" />
    </navigator>
  </view>
  <view class="right-content">
    <navigator url="/pages/good/list/list?category2Id={{ activeList[1].category2Id }}">
      <image src="{{ activeList[1].imageUrl }}" mode="" />
    </navigator>
    <navigator url="/pages/good/list/list?category2Id={{ activeList[2].category2Id }}">
      <image src="{{ activeList[2].imageUrl }}" mode="" />
    </navigator>
  </view>
</view>

pages/index/index.scss

// 活动区
.content {
  height: 400rpx;
  display: flex;
  margin: 16rpx;
  background-origin: content-box;
  background-color: #fff;
  .left-content {
    width: 360rpx;
    border-radius: 10rpx;
    margin-right: 10rpx;
    navigator {
      image {
        width: 100%;
        height: 400rpx;
      }
    }

  }

  .right-content {
    navigator {
      image {
        width: 348rpx;
        border-radius: 10rpx;
        height: 196rpx;

        &:first-child {
          margin-top: 0;
        }
      }
    }

  }
}

4. 猜你喜欢

0. 效果图

1. 创建全局组件

1. 创建 components/goods-list 全局组件

2. 创建 components/goods-card 全局组件: 单独一个商品

3. 在 index 页面注册 goods-list 全局组件

pages/index/index.json

{
  "usingComponents": {
    "goods-list": "../../components/goods-list/goos-list"
  }
}

4. 在 index 页面使用 goods-list 组件

pages/index/index.wxml

<!-- 猜你喜欢 -->
<goods-list />
<!-- 人气推荐 -->
<goods-list />

5. 在 goods-list 组件注册 goods-card 全局组件

components/goods-list/goods-list.json

{
  "usingComponents": {
    "goods-card": "../goods-card/goods-card"
  }
}

6. 在 goods-list 页面使用 goods-card 组件

components/goods-list/goods-list.wxml

<goods-card goodItem="{{ item }}"></goods-card>

2. 页面构建

components/goods-list/goods-list.wxml

<!-- 商品列表 -->
<view class="goods_container">
  <!-- 标题 -->
  <view class="goods_title">{{ title }}</view>

  <!-- 列表区域 -->
  <view class="goods_card_list">
    <goods-card></goods-card>
  </view>

  <!-- 查看更多 -->
  <view class="goods_more">查看更多</view>
</view>

components/goods-list/goods-list.scss

.goods_container {
  width: 100%;

  // 标题
  .goods_title {
    padding: 20rpx 16rpx;
    align-items: center;
    display: flex;
    justify-content: center;
    font-size: 40rpx;
    font-weight: 1000;
  }

  // 商品卡片列表
  .goods_card_list {
    display: flex;
    flex-wrap: wrap
  }
  
  // 查看更多
  .goods_more {
    padding: 20rpx 16rpx;
    align-items: center;
    display: flex;
    justify-content: center;
    font-size: 25rpx;
    font-weight: 100;
    background-color: #fff;
    border-radius: 30rpx;
    margin: 20rpx 16rpx;
  }
}

iconfont/iconfont.cscc

@font-face {
  font-family: "iconfont"; /* Project id 4590971 */
  src: 
       url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
       url('//at.alicdn.com/t/c/font_4590971_zc6rr70adlo.woff?t=1719306935805') format('woff'),
       url('//at.alicdn.com/t/c/font_4590971_zc6rr70adlo.ttf?t=1719306935805') format('truetype');
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-jiarugouwuche:before {
  content: "\e615";
}

.icon-ic_jiarugouwuche:before {
  content: "\e69c";
}

.icon-meiguihua:before {
  content: "\e602";
}

.icon-huahonghuazhiwuhuaduo:before {
  content: "\e622";
}

components/goods-card/goods-card.wxml

<!-- 列表分类卡片 -->
<view class="goods_card_container">
  <!-- 跳转商品详情 -->
  <navigator class="navigator_nav" url="/pages/goods/detail/detail?goodsId={{ goodItem.id }}">
    <image class="good_img" src="{{ goodItem.imageUrl }}" mode="" />
    <view class="title">
      <text class="title_txt">{{ goodItem.material }}</text>
    </view>
    <view class="content">
      <text class="content_txt">{{ goodItem.floralLanguage }}</text>
    </view>
    <view class="bottom">
      <view class="bottom_container">
        <view class="xian">
          <text class="text">¥</text>{{ goodItem.price }}
        </view>
        <view class="yuan">
          <text class="text">¥</text>{{ goodItem.marketPrice }}
        </view>
        <view class="in_cart">
          <navigator url="">
            <text class="iconfont icon-jiarugouwuche"></text>
          </navigator>
        </view>
      </view>
    </view>
  </navigator>
</view>

components/goods-card/goods-card.scss

@import '@/iconfont/iconfont.scss';

.goods_card_container {
  margin: 20rpx 16rpx;
  width: 340rpx;
  height: 590rpx;
  background-color: #fff;

  .navigator_nav {
    width: 100%;

    .good_img {
      width: 100%;
      height: 350rpx;
    }

    .title {
      width: 100%;
      font-size: 32rpx;
      font-weight: 1000;
      padding: 20rpx 16rpx;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
	
    .content {
      font-size: 25rpx;
      font-weight: 100;
      margin: 30rpx 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      padding: 0 16rpx;
    }
      
    // 底部价格 + 购物车

    .bottom {
      padding: 0 16rpx;

      .bottom_container {
        display: flex;
        align-items: center;

        .xian {
          color: #f3514f;
        }

        .yuan {
          margin-left: 20rpx;
          font-size: 16rpx;
          text-decoration: line-through;
        }
      }
    }
	
    // 加入购物车
    .in_cart {
      background-color: #f3514f;
      border-radius: 50%;
      width: 50rpx;
      height: 50rpx;
      text-align: center;
      margin-left: 90rpx;
      .iconfont {
        color: #fff;
      }
    }
  }

}

3. 数据交互

1. 将 index 请求回来的数据, 传递到组件 goods-list 组件内

pages/index/index.wxml

<!-- 猜你喜欢 -->
<goods-list title="猜你喜欢" list="{{ guessList }}"/>

2. goods-list 组件接收数据

components/goods-list/goods-list.js

Component({
  properties: {
    // 列表标题
    title: {
      type: String,
      value: ''
    },
    // 列表数据
    list: {
      type: Array,
      value: []
    }
  },
})

3. 根据数据循环生成商品卡片

components/goods-list/goods-list.wxml

<!-- 商品列表 -->
<view class="goods_container">
  <!-- 标题 -->
  <view class="goods_title">{{ title }}</view>

  <!-- 列表区域 -->
  <view class="goods_card_list">
  <block wx:for="{{ list }}" wx:key="id">
    <goods-card goodItem="{{ item }}"></goods-card>
  </block>
  </view>

  <!-- 查看更多 -->
  <view class="goods_more">查看更多</view>
</view>

4. 渲染商品卡片数据

components/goods-card/goods-card.wxml

<!-- 列表分类卡片 -->
<view class="goods_card_container">
  <navigator class="navigator_nav" url="/modules/goodModule/pages/goods/detail/detail?goodsId={{ goodItem.id }}">
    <image class="good_img" src="{{ goodItem.imageUrl }}" mode="" />
    <view class="title">
      <text class="title_txt">{{ goodItem.material }}</text>
    </view>
    <view class="content">
      <text class="content_txt">{{ goodItem.floralLanguage }}</text>
    </view>
    <view class="bottom">
      <view class="bottom_container">
        <view class="xian">
          <text class="text">¥</text>{{ goodItem.price }}
        </view>
        <view class="yuan">
          <text class="text">¥</text>{{ goodItem.marketPrice }}
        </view>
        <view class="in_cart">
          <navigator url="">
            <text class="iconfont icon-ic_jiarugouwuche"></text>
          </navigator>
        </view>
      </view>
    </view>
  </navigator>
</view>

5. 人气推荐

pages/index/index.wxml

<goods-list title="人气推荐" list="{{ hotList }}"/>

6. 骨架屏

1. 什么是骨架屏

骨架屏是页面的一个空白版本, 开发者会使用 CSS 绘制一些灰色的区块, 将页面内容大致够了出轮廓,通常会在页面完全渲染之前, 将骨架屏代码进行展示, 待数据加载完成后, 再替换成真实的内容, 骨架屏的设置旨在优化用户体验

在进行项目开发时, 我们需要手工维护骨架屏的代码, 当业务变更时, 同样需要对骨架屏代码进行调整, 为了方便开发者进行骨架屏的绘制, 开发者工具提供了自动生成骨架屏代码的能力

2. 使用步骤

1. 使用微信开发者工具为当前正在预览的页面生成骨架屏代码, 工具入口位于模拟器面板右下角的三点处

2. 生成骨架屏后的页面样式

3. index 下新建skeleton文件夹, 用于存放骨架屏代码

4. 当前正在预览的页面.wxml 中引入模版

pages/index/index.wxml

<!-- 引入骨架屏 -->
<import src="./skeleton/index.skeleton" />
<!-- 使用骨架屏 -->
<template is="skeleton" wx:if="{{loading}}" />

<!-- 真实页面结构,添加 wx:else -->
<view class="index-container" wx:else>
</view>

5. 修改样式文件为 .scss 结尾

6. 当前正在预览的页面.scss 中引入样式文件

pages/index/index.scss

// 引入骨架屏样式文件
@import "./skeleton/index.skeleton.scss";
// 整个页面样式
.index-container {
}

7. 当前正在预览的页面.js 中 定义 loading 来控制是否显示骨架屏

pages/index/index.js

import {
  reqIndexData
} from '@/api/index'
Page({
  data: {
    bannerList: [], // 轮播图
    categoryList: [], // 商品导航
    activeList: [], // 活动区
    hotList: [], // 热门商品(人气推荐)
    guessList: [], // 猜你喜欢
    loading: true  // 是否显示骨架屏,默认显示
  },
  // 获取首页数据
  async getIndexData() {
    const res = await reqIndexData()
    this.setData({
      bannerList: res[0].data,
      categoryList: res[1].data,
      activeList: res[2].data,
      hotList: res[3].data,
      guessList: res[4].data,
      loading: false    // 在得到真实数据后, 不再显示骨架屏
    })
  },
  // 监听页面的加载
  onLoad() {
    // 在页面加载以后, 调用获取首页数据的方法
    this.getIndexData()
  }
})

3. 处理警告

index.skeleton.wxml

<!-- 由于这个标签中有行内样式的原因 -->
<swiper-item class="banner--swiper-item" style="position: absolute; width: 100%; height: 100%; transform: translate(0%, 0px) translateZ(0px);">
</swiper-item>

index.skeleton.wxml 修改后

<swiper-item class="banner--swiper-item swiper-item-1" 
</swiper-item>

index.skeleton.scss

.swiper-item-1 {
  position: absolute;
  width: 100%;
  height: 100%;
  transform: translate(0%, 0px) translateZ(0px);
}
posted @ 2024-07-04 15:32  河图s  阅读(19)  评论(0)    收藏  举报