1. 效果

在这里插入图片描述

2. 分析接口数据

在这里插入图片描述

3. 获取分类页面的数据接口

https://api-hmugo-web.itheima.net/api/public/v1/categories

4. 调用接口

(1)为了方便演示,添加一个编译模式
在这里插入图片描述

(2)现在分类页面的index.js文件中创建三个空数组
index.js

data: {
    // 左侧的菜单数据
    leftMenuList: [],
    // 右侧的商品数据
    rightContent: []
  },
// 为了方便使用数据,在data同层级下创建Cates空数组接收接口返回的数据
Cates: [],

(3)发送异步请求给三个空数组赋值
index.js

// 引入用来发送请求的方法 一定要把路径补全
import {request} from "../../request/index.js"
Page({
  /**
   * 页面的初始数据
   */
  data: {
    // 左侧的菜单数据
    leftMenuList: [],
    // 右侧的商品数据
    rightContent: []
  },
  // 为了方便使用数据,在data同层级下创建Cates空数组接收接口返回的数据
  Cates: [],
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.getCates();
  },
  // 获取轮播图数据
  getCates(){
    request({url: 'https://api-hmugo-web.itheima.net/api/public/v1/categories'})
      .then(res=>{
        this.Cates = res.data.message;
        // 构造左侧的大菜单数据
        let leftMenuList = this.Cates.map(v=>v.cat_name);
        // 构造右侧的大菜单数据
        let rightContent = this.Cates[0].children;
        this.setData({
          leftMenuList,
          rightContent
        })
      })
  },
})

5. 页面布局

index.wxml

<view class="cates">
  <!-- 搜索框开始 -->
  <SearchInput></SearchInput>
  <!-- 搜索框结束 -->
  <view class="cates_container">
    <!-- 左侧的菜单数据开始 -->
    <scroll-view scroll-y class="left_menu">
      <!-- *this指的是for循环中item本身 -->
      <!-- 注意:要在index.js 先写死 currentIndex:0 -->
      <view
       class="menu_item {{index===currentIndex?'active':''}}"
       wx:for="{{leftMenuList}}"
       wx:key="*this"
      >
        <view>
          {{item}}
        </view>
      </view>
    </scroll-view>
    <!-- 左侧的菜单数据结束 -->
    <!-- 右侧的菜单数据开始 -->
    <scroll-view scroll-y class="right_content">
      <!-- 由于 goods_group中没有什么是唯一的属性所以-->
      <view
       class="goods_group"
       wx:for="{{rightContent}}"
       wx:key="*this"
       wx:for-index="index1"
       wx:for-item="item1"
      >
        <view class="goods_title">
          <text class="delimeter">/</text>
          <text class="title">{{item1.cat_name}}</text>
          <text class="delimeter">/</text>
        </view>
        <view class="goods_list">
          <navigator
           wx:for="{{item1.children}}"
           wx:for-item="item2"
           wx:for-index="index2"
           wx:key="cat_id"
          >
            <image mode="widthFix" src="{{item2.cat_icon}}" />
            <view class="goods_name">{{item2.cat_name}}</view>
          </navigator>
        </view>
      </view>
    </scroll-view>
    <!-- 右侧的菜单数据结束 -->
  </view>
</view>

index.less

page{
  // 先设置父页面高度
  height: 100%;
}
.cates{
  // 继承父页面高度
  height: 100%;
  .cates_container{
    // less中使用calc的时候要使用 ~ 包裹
    height: ~'calc( 100vh - 90rpx )';
    display: flex;
    .left_menu{
      // 因为现在是伸缩盒子的子项 有默认高度 100%
      flex: 2;
      .menu_item{
        display: flex;
        height: 80rpx;
        justify-content: center;
        align-items: center;
        font-size: 30rpx;
      }
      .active{
        color: var(--themeColor);
        border-left: 5rpx solid currentColor;
      }
    }
    .right_content{
      // 因为现在是伸缩盒子的子项 有默认高度 100%
      flex: 5;
      .goods_group{
        .goods_title{
          height: 80rpx;
          display: flex;
          justify-content: center;
          align-items: center;
          .delimeter{
            color: #ccc;
            padding: 0 10rpx;
          }
          .title{}
        }
        .goods_list{
          display: flex;
          // 允许换行
          flex-wrap: wrap;
          navigator{
            width: 33.33%;
            // 文字图片居中对齐
            text-align: center;
            image{
              width: 50%;
            }
          }
          .goods_name{
          
          }
        }
      }
    }
  }
}

app.wxss

image{
  /* 定义所有图片的宽度格式 */
  width: 100%;
}

在这里插入图片描述

6. 点击菜单可切换商品种类

修改左侧菜单的页面布局

<!-- 左侧的菜单数据开始 -->
    <scroll-view scroll-y class="left_menu">
      <!-- *this指的是for循环中item本身 -->
      <view
       class="menu_item {{index===currentIndex?'active':''}}"
       wx:for="{{leftMenuList}}"
       wx:key="*this"
       bindtap="handleItemTap"
       data-index="{{index}}"
      >
        <view>
          {{item}}
        </view>
      </view>
    </scroll-view>
    <!-- 左侧的菜单数据结束 -->

添加点击事件的行为
index.js

// 引入用来发送请求的方法 一定要把路径补全
import {request} from "../../request/index.js"
Page({
  /**
   * 页面的初始数据
   */
  data: {
    // 左侧的菜单数据
    leftMenuList: [],
    // 右侧的商品数据
    rightContent: [],
    currentIndex: 0
  },
  // 为了方便使用数据,在data同层级下创建Cates空数组接收接口返回的数据
  Cates: [],
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    wx.request({
      url: 'url',
    })
    this.getCates();
  },
  // 获取轮播图数据
  getCates(){
    request({url: 'https://api-hmugo-web.itheima.net/api/public/v1/categories'})
      .then(res=>{
        this.Cates = res.data.message;
        // 构造左侧的大菜单数据
        let leftMenuList = this.Cates.map(v=>v.cat_name);
        // 构造右侧的大菜单数据
        let rightContent = this.Cates[0].children;
        this.setData({
          leftMenuList,
          rightContent
        })
      })
  },
  //左侧菜单点击事件
  handleItemTap(e){
    /* 
    1 获取被点击的标题身上的索引
    2 给data中的currentIndex赋值就可以了
    3 根据不同的索引来渲染右侧的商品内容
     */
    const {index} = e.currentTarget.dataset;
    let rightContent = this.Cates[index].children;
    this.setData({
      currentIndex:index,
      rightContent
    })
  }
})

在这里插入图片描述

7. 使用缓存技术

思路:在打开页面的时候,先做一个判断,判断本地储存中有没有旧的数据,如果没有的话,就发送请求获取这个数据,假如说有旧的数据,并且这个数据没有过期,那么此时就可以使用本地储存中旧的数据了。所以说,我们需要解决的是怎么去存数据怎么去拿数据

index.js

// 引入用来发送请求的方法 一定要把路径补全
import {request} from "../../request/index.js"
Page({
  /**
   * 页面的初始数据
   */
  data: {
    // 左侧的菜单数据
    leftMenuList: [],
    // 右侧的商品数据
    rightContent: [],
    currentIndex: 0
  },
  // 为了方便使用数据,在data同层级下创建Cates空数组接收接口返回的数据
  Cates: [],
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    /*
      1 先判断一下本地存储中有没有旧的数据
        {time:Date.now(),data:[...]}
      2 没有旧数据 直接发送新请求 
      3 有旧的数据 同时 旧的数据也没有过期 就使用 本地存储中的旧数据即可
    */
    //  1 获取本地存储中的数据  (小程序中也是存在本地存储 技术)
    const Cates = wx.getStorageSync('cates');
    //  2 判断  
    if(!Cates){
      // 不存在 发送请求获取数据
      this.getCates();
    }else{
      // 有旧的数据 定义过期时间5分钟 1000ms = 1s
      if(Date.now()-Cates.time>1000*300){
        // 重新发送请求
        this.getCates();
      }else{
        this.Cates = Cates.data;
        // 构造左侧的大菜单数据
        let leftMenuList = this.Cates.map(v=>v.cat_name);
        // 构造右侧的大菜单数据
        let rightContent = this.Cates[0].children;
        this.setData({
          leftMenuList,
          rightContent
        })
      }
    }
  },
  // 获取轮播图数据
  getCates(){
    request({url: 'https://api-hmugo-web.itheima.net/api/public/v1/categories'})
      .then(res=>{
        this.Cates = res.data.message;
        // 把接口的数据存入到本地存储中
        wx.setStorageSync("cates", { time: Date.now(), data: this.Cates });
        // 构造左侧的大菜单数据
        let leftMenuList = this.Cates.map(v=>v.cat_name);
        // 构造右侧的大菜单数据
        let rightContent = this.Cates[0].children;
        this.setData({
          leftMenuList,
          rightContent
        })
      })
  },
  //左侧菜单点击事件
  handleItemTap(e){
    /* 
    1 获取被点击的标题身上的索引
    2 给data中的currentIndex赋值就可以了
    3 根据不同的索引来渲染右侧的商品内容
     */
    const {index} = e.currentTarget.dataset;
    let rightContent = this.Cates[index].children;
    this.setData({
      currentIndex:index,
      rightContent
    })
  }
})
疑惑:web和小程序本地存储的区别

1 写代码的方式不一样了
web: localStorage.setItem(“key”,“value”) localStorage.getItem(“key”)
小程序中: wx.setStorageSync(“key”, “value”); wx.getStorageSync(“key”);

2 存的时候 有没有做类型转换
web: 不管存入的是什么类型的数据,最终都会先调用一下 toString(),把数据变成了字符串 再存入进去
小程序: 不存在 类型转换的这个操作 存什么类似的数据进去,获取的时候就是什么类型

8. 点击菜单-右侧列表置顶

如果你跟着我敲的话,你会发现当你点击一个菜单后,右侧列表往下拉,再点击另一个菜单,你会发现右侧列表没有置顶,那么怎么做呢?👇👇👇

思路:在右侧的菜单数据的 scroll-view 标签中增加 scroll-top 属性设置竖向滚动条位置,但这标签不能写死,如 scroll-top=“0”,因为这对于触发点击事件无效,你得设置一个变量,当点击左边菜单时,对这个变量赋值

index.wxml

<!-- 右侧的菜单数据开始 -->
    <scroll-view
     scroll-y
     class="right_content"
     scroll-top="{{scrollTop}}"
    >
    。。。
    <scroll-view/>

index.js

data: {
    // 左侧的菜单数据
    leftMenuList: [],
    // 右侧的商品数据
    rightContent: [],
    currentIndex: 0,
    scrollTop:0
  },
。。。

// 左侧菜单的点击事件
  handleItemTap(e) {
    /* 
    1 获取被点击的标题身上的索引
    2 给data中的currentIndex赋值就可以了
    3 根据不同的索引来渲染右侧的商品内容
     */
    const { index } = e.currentTarget.dataset;
    let rightContent = this.Cates[index].children;
    this.setData({
      currentIndex: index,
      rightContent,
      // 重新设置 右侧内容的scroll-view标签的距离顶部的距离
      scrollTop: 0
    })
  }
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐